J'ai une table PostgreSQL 9.3 avec quelques chiffres et quelques données supplémentaires:
CREATE TABLE mytable (
myid BIGINT,
somedata BYTEA
)
Cette table compte actuellement environ 10 millions d'enregistrements et occupe 1 Go d'espace disque. myid
ne sont pas consécutifs.
Je veux calculer le nombre de lignes dans chaque bloc de 100 000 nombres consécutifs:
SELECT myid/100000 AS block, count(*) AS total FROM mytable GROUP BY myid/100000;
Cela renvoie environ 3500 lignes.
J'ai remarqué que l'existence d'un certain index accélère considérablement cette requête même si le plan de requête ne le mentionne pas du tout. Le plan de requête sans l'index:
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'index:
db=> CREATE INDEX myindex ON mytable ((myid/100000));
db=> VACUUM ANALYZE;
Le nouveau plan de requête:
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)
Ainsi, les plans de requête et les temps d'exécution diffèrent considérablement (près de trois fois) mais ne mentionnent pas l'index. Ce comportement est parfaitement reproductible sur ma machine de développement: j'ai effectué plusieurs cycles de suppression de l'index, de test de la requête plusieurs fois, de recréation de l'index, de nouveau de tester la requête plusieurs fois. Qu'est-ce qu'il se passe ici?
explain (analyze true, verbose true) ...
:?
HashAggregate
méthode (et aucun tri n'est requis), donc vous obtenez de meilleures performances. Pourquoi l'indice n'est pas mentionné dans le plan, je n'en ai aucune idée.