8

Tengo una tabla t con una columna c, que es una int y tiene un índice btree en ella.PostgreSQL: ¿Por qué esta simple consulta no utiliza el índice?

¿Por qué la siguiente consulta no utiliza este índice?

explain select c from t group by c; 

El resultado que obtengo es:

HashAggregate (cost=1005817.55..1005817.71 rows=16 width=4) 
    -> Seq Scan on t (cost=0.00..946059.84 rows=23903084 width=4) 

Mi comprensión de los índices es limitada, pero pensé que este tipo de consultas fueron el objetivo de los índices.

Respuesta

4

La consulta ciertamente puede usar un índice. La razón por la que no lo hace en su caso particular depende del tamaño particular y la distribución de los datos. Puede usar SET enable_seqscan TO off para investigar.

+2

¿Bajo qué circunstancias no sería rentable no usar un índice? No puedo imaginar ninguna distribución al menos cuando estamos hablando del tamaño en este ejemplo. – David

+0

@David: una exploración de índice completo es mucho más costosa que una exploración secuencial de la tabla. Un índice generalmente solo sería útil si selecciona un pequeño subconjunto de la tabla. –

+1

Esto es simplemente incorrecto. Una consulta como 'SELECT DISTINCT x FROM t;' debería poder usar un índice en '(x)'. Leer el índice completo debería ser menos costoso que leer toda la tabla. Pero Postgres no ha implementado por lo que sé [exploraciones de índice suelto] (https://wiki.postgresql.org/wiki/Loose_indexscan) –

3

Debido a que requiere escanear toda la tabla, hacer eso a través del índice no es beneficioso. (Los "índices de cobertura" no son útiles como técnica de rendimiento en PostgreSQL debido a su implementación de MVCC).

+0

PostgreSQL 9.2 vendrá con escaneos indexados: http://wiki.postgresql.org/wiki/What%27s_new_in_PostgreSQL_9.2#Index-only_scans – qerub

5

Esta consulta se puede realizar utilizando una optimización llamada exploración de índice suelto. Sin embargo, PostgreSQL aún no implementa esta optimización, por lo que utiliza una exploración de tabla en su lugar.

De las principales bases de datos, hasta donde sé, solo MySQL has implemented loose index scan (¿quizás Oracle también?). PostgreSQL hasn't implementó esta característica.

+0

La arquitectura de Postgresql significa que actualmente TIENE que visitar la tabla incluso si utiliza El índice. Eso es mucho más caro cuando tienes que golpear cada fila de todos modos. Supongo que en mysql el motor debería incluir índices de cobertura para funcionar correctamente, pero no sé muy bien qué es MySQL. –

+3

@Scott Marlowe: Pero el punto principal es que si se puede usar un escaneo de índice suelto, * no * tiene que golpear cada fila. Es por eso que MySQL puede ser cientos o miles de veces más rápido que PostgreSQL para este tipo de consulta (en tablas muy grandes donde hay muy pocos valores distintos de 'c'). Es una solicitud de función de baja prioridad porque un simple cambio en el diseño del esquema (presentación de una nueva tabla) resuelve el problema. –

+1

También se lo conoce como * index only scan * y Oracle, SQL Server y DB2 implementan esto también. Pero dudo que haga una consulta * miles de veces más rápido *. Más rápido, sí. Pero no en ese orden de magnitud (pero estoy de acuerdo, es realmente una lástima que Postgres no tenga eso) –

Cuestiones relacionadas