Sont-ils équivalents? Si non alors pourquoi?
Index (user_id1, user_id2) et index (user_id2, user_id1)
Ce ne sont pas équivalents et généralement index (bar, baz) ne sera pas efficace pour les requêtes de la forme select * from foo where baz=?
Erwin a démontré que de tels index peuvent effectivement accélérer une requête, mais cet effet est limité et n’est pas du même ordre que celui attendu d’un index pour améliorer une recherche. Il repose sur le fait qu’un «balayage complet» d’un index est souvent plus rapide qu'une "analyse complète" de la table indexée en raison des colonnes supplémentaires de la table qui n'apparaissent pas dans l'index.
Résumé: les index peuvent aider les requêtes même sur les colonnes non-principales, mais de deux manières secondaire et relativement mineure, et non de la manière dramatique que vous attendez normalement d'un index en raison de sa structure btree
Les deux manières dont l'index peut aider sont si une analyse complète de l'indice est beaucoup moins chère qu'une analyse complète du tableau et soit: 1. les recherches dans le tableau sont peu coûteuses (car elles sont peu nombreuses ou sont regroupées), ou 2. l'index est couvrant donc il n'y a pas de consultation de table à tous les oops, voir les commentaires d'Erwins ici
banc d'essai:
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;
Requête 1 (pas d'index, frappant 74 tampons ):
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
requête 2 (avec index - l'optimiseur ignore l'index - frappe à nouveau 74 tampons ):
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
requête 2 (avec index - et nous trompons l'optimiseur pour l'utiliser):
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
Ainsi, l'accès via l'index est deux fois plus rapide dans ce cas, atteignant 30 tampons - ce qui en termes d'indexation est "légèrement plus rapide" !, et YMMV en fonction de la taille relative de la table et de l'index, ainsi que du nombre de lignes filtrées et des caractéristiques de clustering. des données dans la table
En revanche, les requêtes sur la colonne de tête utilisent la structure btree de l'index. Dans ce cas, deux tampons sont activés :
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