Sono equivalenti? Se no allora perché?
Index (user_id1, user_id2) e Index (user_id2, user_id1)
Questi non sono equivalenti e l'indice in generale (bar, baz) non sarà efficace per le query del modulo select * from foo where baz=?
Erwin ha dimostrato che tali indici possono effettivamente accelerare una query, ma questo effetto è limitato e non dello stesso ordine in cui ci si aspetta che un indice migliori una ricerca - si basa sul fatto che una "scansione completa" di un indice è spesso più veloce di una "scansione completa" della tabella indicizzata a causa delle colonne extra nella tabella che non compaiono nell'indice.
Riepilogo: gli indici possono aiutare le query anche su colonne non iniziali, ma in uno dei due modi secondari e relativamente minori e non nel modo drammatico che normalmente ti aspetti che un indice aiuti a causa della sua struttura btree
nb i due modi in cui l'indice può aiutare sono se una scansione completa dell'indice è significativamente più economica di una scansione completa della tabella e sia: 1. le ricerche della tabella sono economiche (perché ce ne sono poche o sono raggruppate), oppure 2. l'indice copre quindi non ci sono ricerche di tabella a tutti gli spiacenti, vedere i commenti di Erwins qui
banco di prova:
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;
query 1 (nessun indice, colpendo 74 buffer ):
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
query 2 (con indice - l'ottimizzatore ignora l'indice - colpendo nuovamente 74 buffer ):
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
query 2 (con indice - e inganniamo l'ottimizzatore per usarlo):
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
Quindi l'accesso tramite l'indice è due volte più veloce in questo caso colpendo 30 buffer - che in termini di indicizzazione è 'leggermente più veloce'! E YMMV a seconda della dimensione relativa di tabella e indice, insieme al numero di righe filtrate e caratteristiche di clustering dei dati nella tabella
Al contrario, le query sulla colonna principale fanno uso della struttura btree dell'indice, in questo caso colpendo 2 buffer :
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