tl;dr Debe agregar un índice en item_id
. La "magia negra" de la indexación de Postgres se trata en 11. Índices
.
Tiene un índice compuesto en (topic_id, item_id)
y el orden de las columnas es importante. Postgres puede usar esto para indexar consultas en topic_id
, consultas en ambos topic_id
y item_id
, pero no (o menos eficientemente) item_id
solo.
De 11.3. Índices de varias columnas ...
-- indexed
select *
from topics_items
where topic_id = ?
-- also indexed
select *
from topics_items
where topic_id = ?
and item_id = ?
-- probably not indexed
select *
from topics_items
where item_id = ?
Esto se debe a que un índice compuesto como (topic_id, item_id)
primero almacena el ID del tema, luego un ID de elemento que también tiene ese ID de tema. Para buscar una identificación de elemento de manera eficiente en este índice, Postgres primero debe restringir la búsqueda con una identificación de tema.
Postgres puede invertir un índice si cree que vale la pena el esfuerzo. Si hay una pequeña cantidad de ID de tema posibles y una gran cantidad de ID de índice posibles, buscará la ID de índice en cada ID de tema.
Por ejemplo, supongamos que tiene 10 ID de temas posibles y 1000 ID de elementos posibles y su índice (topic_id, index_id)
. Esto es como tener 10 cubos de ID de tema claramente etiquetados, cada uno con 1000 cubos de ID de artículo claramente etiquetados en su interior. Para llegar a los depósitos de ID de elementos, debe mirar dentro de cada depósito de ID de tema. Para usar este índice en where item_id = 23
Postgres debe buscar en cada uno de los 10 depósitos de ID de tema todos los depósitos con el ID de elemento 23.
Pero si tiene 1000 ID de temas posibles y 10 ID de elementos posibles, Postgres tendría que buscar 1000 cubos de ID de temas. Lo más probable es que haga un escaneo completo de la tabla en su lugar. En este caso, querrá invertir su índice y convertirlo en (item_id, topic_id)
.
Esto depende en gran medida de tener buenas estadísticas de la tabla, lo que significa asegurarse de que el vacío automático funcione correctamente.
Por lo tanto, puede salirse con la suya con un solo índice para dos columnas, si una columna tiene mucha menos variabilidad que otra.
Postgres también puede usar múltiples índices si cree que hará que la consulta se ejecute más rápido
. Por ejemplo, si tuviera un índice en topic_id
y un índice en item_id
, puede utilice ambos índices y combine los resultados. Por ejemplo, where topic_id = 23 or item_id = 42
podría usar el índice topic_id para buscar el ID de tema 23 y el índice item_id para buscar el ID de elemento 42 y luego combinar los resultados.
Esto es generalmente más lento que tener un (topic_id, item_id)
compuesto índice. También puede ser más lento que usar un solo índice, así que no se sorprenda si Postgres decide no usar múltiples índices.
En general, para los índices de árbol b, cuando tiene dos columnas, tiene tres combinaciones posibles.
- a + b
- a
- b
Y necesitas dos índices.
- (a, b) -- a y a + b
- (b) -- b
(a, b)
cubre tanto las búsquedas de a como de a + b. (b)
cubre la búsqueda de b
.
Cuando tienes tres columnas, tienes siete combinaciones posibles.
- a + b + c
- a + b
- a + c
- a
- b + c
- b
- c
Pero solo necesitas tres índices.
- (a, b, c) -- a, a + b, a + b + c
- (b, c) -- b, b + c
- (c, a) -- c, c + a
Sin embargo, probablemente desee evitar tener un índice en tres columnas. A menudo es más lento . Lo que realmente quieres es esto.
- (a, b)
- (b,c)
- (c, a)
Leer de un índice es más lento que leer de la tabla. Desea que sus índices reduzcan el número de filas que se deben leer, pero no desea que Postgres tenga que realizar más análisis de índices de los necesarios.