¿Son estos equivalentes? Si no es así, ¿por qué?
Index (user_id1, user_id2) e Index (user_id2, user_id1)
Estos no son equivalentes y, en general, el índice (bar, baz) no será eficiente para consultas del formulario select * from foo where baz=?
Erwin ha demostrado que tales índices pueden acelerar una consulta, pero este efecto es limitado y no es del mismo orden que generalmente se espera que un índice mejore una búsqueda: se basa en el hecho de que a menudo se realiza una 'exploración completa' de un índice más rápido que una 'exploración completa' de la tabla indexada debido a las columnas adicionales en la tabla que no aparecen en el índice.
Resumen: los índices pueden ayudar a las consultas incluso en columnas no iniciales, pero de una de las dos formas secundarias y relativamente menores y no de la forma dramática que normalmente espera que un índice ayude debido a su estructura btree
nb las dos formas en que el índice puede ayudar son si un análisis completo del índice es significativamente más barato que un análisis completo de la tabla y: 1. las búsquedas de la tabla son baratas (porque hay pocas o están agrupadas), o 2. el índice está cubriendo, por lo que no hay búsquedas de tablas en absoluto , vea los comentarios de Erwins aquí
banco de pruebas:
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;
consulta 1 (sin índice, golpeando 74 buffers ):
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
consulta 2 (con índice - el optimizador ignora el índice - golpeando 74 buffers nuevamente):
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
consulta 2 (con índice, y engañamos al optimizador para que lo use):
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
Por lo tanto, el acceso a través del índice es el doble de rápido en este caso, llegando a 30 buffers , ¡lo que en términos de indexación es 'ligeramente más rápido'! de los datos en la tabla
Por el contrario, las consultas en la columna inicial hacen uso de la estructura btree del índice, en este caso golpeando 2 buffers :
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