Tengo una tabla PostgreSQL 9.3 con algunos números y algunos datos adicionales:
CREATE TABLE mytable (
myid BIGINT,
somedata BYTEA
)
Actualmente, esta tabla tiene aproximadamente 10 millones de registros y ocupa 1 GB de espacio en disco. myid
No son consecutivos.
Quiero calcular cuántas filas hay en cada bloque de 100000 números consecutivos:
SELECT myid/100000 AS block, count(*) AS total FROM mytable GROUP BY myid/100000;
Esto devuelve alrededor de 3500 filas.
Noté que la existencia de un cierto índice acelera significativamente esta consulta a pesar de que el plan de consulta no lo menciona en absoluto. El plan de consulta sin el índice:
db=> EXPLAIN (ANALYZE TRUE, VERBOSE TRUE) SELECT myid/100000 AS block, count(*) AS total FROM mytable GROUP BY myid/100000;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------
GroupAggregate (cost=1636639.92..1709958.65 rows=496942 width=8) (actual time=6783.763..8888.841 rows=3460 loops=1)
Output: ((myid / 100000)), count(*)
-> Sort (cost=1636639.92..1659008.91 rows=8947594 width=8) (actual time=6783.752..8005.831 rows=8947557 loops=1)
Output: ((myid / 100000))
Sort Key: ((mytable.myid / 100000))
Sort Method: external merge Disk: 157440kB
-> Seq Scan on public.mytable (cost=0.00..236506.92 rows=8947594 width=8) (actual time=0.020..1674.838 rows=8947557 loops=1)
Output: (myid / 100000)
Total runtime: 8914.780 ms
(9 rows)
El índice:
db=> CREATE INDEX myindex ON mytable ((myid/100000));
db=> VACUUM ANALYZE;
El nuevo plan de consulta:
db=> EXPLAIN (ANALYZE TRUE, VERBOSE TRUE) SELECT myid/100000 AS block, count(*) AS total FROM mytable GROUP BY myid/100000;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------
HashAggregate (cost=281242.99..281285.97 rows=3439 width=8) (actual time=3190.189..3190.800 rows=3460 loops=1)
Output: ((myid / 100000)), count(*)
-> Seq Scan on public.mytable (cost=0.00..236505.56 rows=8947485 width=8) (actual time=0.026..1659.571 rows=8947557 loops=1)
Output: (myid / 100000)
Total runtime: 3190.975 ms
(5 rows)
Entonces, los planes de consulta y los tiempos de ejecución difieren significativamente (casi tres veces) pero ninguno menciona el índice. Este comportamiento es perfectamente reproducible en mi máquina de desarrollo: pasé por varios ciclos de caída del índice, probando la consulta varias veces, recreando el índice, nuevamente probando la consulta varias veces. ¿Que esta pasando aqui?
explain (analyze true, verbose true) ...
:?
HashAggregate
método (y no se requiere clasificación), por lo que obtienes un mejor rendimiento. Por qué el índice no se menciona en el plan, no tengo ni idea.