Saya punya tabel PostgreSQL 9.3 dengan beberapa angka dan beberapa data tambahan:
CREATE TABLE mytable (
myid BIGINT,
somedata BYTEA
)
Tabel ini saat ini memiliki sekitar 10 juta catatan dan membutuhkan 1GB ruang disk. myidtidak berturut-turut.
Saya ingin menghitung berapa baris di setiap blok yang berisi 100000 angka berurutan:
SELECT myid/100000 AS block, count(*) AS total FROM mytable GROUP BY myid/100000;
Ini mengembalikan sekitar 3500 baris.
Saya perhatikan bahwa keberadaan indeks tertentu secara signifikan mempercepat kueri ini meskipun rencana kueri tidak menyebutkannya sama sekali. Paket permintaan tanpa indeks:
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)
Indeks:
db=> CREATE INDEX myindex ON mytable ((myid/100000));
db=> VACUUM ANALYZE;
Paket kueri baru:
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)
Jadi, rencana kueri dan runtime berbeda secara signifikan (hampir tiga kali) tetapi tidak disebutkan indeksnya. Perilaku ini dapat direproduksi dengan sempurna di mesin dev saya: Saya mengalami beberapa siklus menjatuhkan indeks, menguji kueri beberapa kali, membuat ulang indeks, dan lagi menguji kueri beberapa kali. Apa yang sedang terjadi disini?
explain (analyze true, verbose true) ...?
HashAggregatemetode ini (dan tidak diperlukan penyortiran), sehingga Anda mendapatkan kinerja yang lebih baik. Mengapa indeks tidak disebutkan dalam rencana, saya belum tahu.