Ho una tabella PostgreSQL 9.3 con alcuni numeri e alcuni dati aggiuntivi:
CREATE TABLE mytable (
myid BIGINT,
somedata BYTEA
)
Questa tabella contiene attualmente circa 10 milioni di record e occupa 1 GB di spazio su disco. myid
non sono consecutivi.
Voglio calcolare quante righe ci sono in ogni blocco di 100000 numeri consecutivi:
SELECT myid/100000 AS block, count(*) AS total FROM mytable GROUP BY myid/100000;
Ciò restituisce circa 3500 righe.
Ho notato che l'esistenza di un certo indice accelera notevolmente questa query anche se il piano di query non lo menziona affatto. Il piano di query senza l'indice:
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)
L'indice:
db=> CREATE INDEX myindex ON mytable ((myid/100000));
db=> VACUUM ANALYZE;
Il nuovo piano di query:
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)
Pertanto, i piani di query e i tempi di esecuzione differiscono in modo significativo (quasi tre volte) ma non menzionano né l'indice. Questo comportamento è perfettamente riproducibile sulla mia macchina di sviluppo: ho attraversato diversi cicli di rilascio dell'indice, testando la query più volte, ricreando l'indice, testando nuovamente la query più volte. Cosa sta succedendo qui?
explain (analyze true, verbose true) ...
?
HashAggregate
metodo (e non è richiesto alcun ordinamento), in modo da ottenere prestazioni migliori. Perché l'indice non è menzionato nel piano, non ne ho idea.