Ich habe eine PostgreSQL 9.3-Tabelle mit einigen Zahlen und einigen zusätzlichen Daten:
CREATE TABLE mytable (
myid BIGINT,
somedata BYTEA
)
Diese Tabelle enthält derzeit ca. 10 Millionen Datensätze und benötigt 1 GB Speicherplatz. myid
sind nicht aufeinanderfolgend.
Ich möchte berechnen, wie viele Zeilen sich in jedem Block mit 100000 aufeinander folgenden Zahlen befinden:
SELECT myid/100000 AS block, count(*) AS total FROM mytable GROUP BY myid/100000;
Dies gibt ungefähr 3500 Zeilen zurück.
Ich habe festgestellt, dass das Vorhandensein eines bestimmten Index diese Abfrage erheblich beschleunigt, obwohl der Abfrageplan dies überhaupt nicht erwähnt. Der Abfrageplan ohne 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)
Der Index:
db=> CREATE INDEX myindex ON mytable ((myid/100000));
db=> VACUUM ANALYZE;
Der neue Abfrageplan:
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)
Die Abfragepläne und die Laufzeiten unterscheiden sich also erheblich (fast dreimal), erwähnen jedoch weder den Index. Dieses Verhalten ist auf meinem Entwicklungscomputer perfekt reproduzierbar: Ich habe mehrere Zyklen durchlaufen, in denen der Index gelöscht, die Abfrage mehrmals getestet, der Index neu erstellt und die Abfrage erneut mehrmals getestet wurde. Was passiert hier?
explain (analyze true, verbose true) ...
?
HashAggregate
Methode verwendet (und es ist keine Sortierung erforderlich), damit Sie eine bessere Leistung erzielen. Warum der Index im Plan nicht erwähnt wird, weiß ich nicht.