これらは同等ですか?そうでない場合、なぜですか?
Index(user_id1、user_id2)およびIndex(user_id2、user_id1)
これらは同等ではなく、一般的に言えば、index(bar、baz)は次の形式のクエリに対して効率的ではありません。 select * from foo where baz=?
アーウィンはそのようなインデックスが実際にクエリを高速化できることを実証しましたが、この効果は制限され、インデックスがルックアップを改善するために一般的に期待するのと同じ順序ではありません-それはインデックスの「フルスキャン」がしばしばテーブル内の余分な列がインデックスに表示されないため、インデックス付きテーブルの「フルスキャン」よりも高速です。
要約:インデックスは、先頭以外の列でもクエリに役立ちますが、2つの二次的な比較的マイナーな方法の1つであり、btree構造のためにインデックスが通常劇的に役立つと期待する方法ではありません
NBインデックスのフルスキャンがテーブルのフルスキャンよりもかなり安いですし、どちらかの場合、インデックスは助けることができる2つの方法がある:1。(そこにそれらのいくつかがあるか、それらがクラスタ化されているので)、テーブルルックアップが安価であり、または2.インデックスがされてカバーするので、全くのテーブルのルックアップはありませんおっと、Erwinsのコメントを参照してくださいここでは、
テストベッド:
create table foo(bar integer not null, baz integer not null, qux text not null);
insert into foo(bar, baz, qux)
select random()*100, random()*100, 'some random text '||g from generate_series(1,10000) g;
クエリ1(インデックスなし、74バッファをヒット):
explain (buffers, analyze, verbose) select max(qux) from foo where baz=0;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------
Aggregate (cost=181.41..181.42 rows=1 width=32) (actual time=3.301..3.302 rows=1 loops=1)
Output: max(qux)
Buffers: shared hit=74
-> Seq Scan on stack.foo (cost=0.00..181.30 rows=43 width=32) (actual time=0.043..3.228 rows=52 loops=1)
Output: bar, baz, qux
Filter: (foo.baz = 0)
Buffers: shared hit=74
Total runtime: 3.335 ms
クエリ2(インデックスあり-オプティマイザはインデックスを無視します- 再度74バッファをヒットします):
create index bar_baz on foo(bar, baz);
explain (buffers, analyze, verbose) select max(qux) from foo where baz=0;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------
Aggregate (cost=199.12..199.13 rows=1 width=32) (actual time=3.277..3.277 rows=1 loops=1)
Output: max(qux)
Buffers: shared hit=74
-> Seq Scan on stack.foo (cost=0.00..199.00 rows=50 width=32) (actual time=0.043..3.210 rows=52 loops=1)
Output: bar, baz, qux
Filter: (foo.baz = 0)
Buffers: shared hit=74
Total runtime: 3.311 ms
クエリ2(インデックス付き-オプティマイザをだまして使用する):
explain (buffers, analyze, verbose) select max(qux) from foo where bar>-1000 and baz=0;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------
Aggregate (cost=115.56..115.57 rows=1 width=32) (actual time=1.495..1.495 rows=1 loops=1)
Output: max(qux)
Buffers: shared hit=36 read=30
-> Bitmap Heap Scan on stack.foo (cost=73.59..115.52 rows=17 width=32) (actual time=1.370..1.428 rows=52 loops=1)
Output: bar, baz, qux
Recheck Cond: ((foo.bar > (-1000)) AND (foo.baz = 0))
Buffers: shared hit=36 read=30
-> Bitmap Index Scan on bar_baz (cost=0.00..73.58 rows=17 width=0) (actual time=1.356..1.356 rows=52 loops=1)
Index Cond: ((foo.bar > (-1000)) AND (foo.baz = 0))
Buffers: shared read=30
Total runtime: 1.535 ms
したがって、この場合、インデックスを介したアクセスは2倍速くなり、30個のバッファにヒットします -インデックス作成に関しては「わずかに高速」です!YMMVは、テーブルとインデックスの相対的なサイズ、フィルタリングされた行の数およびクラスタリング特性に依存しますテーブル内のデータの
対照的に、先頭の列に対するクエリはインデックスのbtree構造を利用します-この場合は2つのバッファをヒットします:
explain (buffers, analyze, verbose) select max(qux) from foo where bar=0;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------
Aggregate (cost=75.70..75.71 rows=1 width=32) (actual time=0.172..0.173 rows=1 loops=1)
Output: max(qux)
Buffers: shared hit=38
-> Bitmap Heap Scan on stack.foo (cost=4.64..75.57 rows=50 width=32) (actual time=0.036..0.097 rows=59 loops=1)
Output: bar, baz, qux
Recheck Cond: (foo.bar = 0)
Buffers: shared hit=38
-> Bitmap Index Scan on bar_baz (cost=0.00..4.63 rows=50 width=0) (actual time=0.024..0.024 rows=59 loops=1)
Index Cond: (foo.bar = 0)
Buffers: shared hit=2
Total runtime: 0.209 ms