Tôi đã có một bảng PostgreSQL 9.3 với một số số và một số dữ liệu bổ sung:
CREATE TABLE mytable (
myid BIGINT,
somedata BYTEA
)
Bảng này hiện có khoảng 10 triệu bản ghi và chiếm 1GB dung lượng đĩa. myid
không liên tiếp.
Tôi muốn tính toán có bao nhiêu hàng trong mỗi khối 100000 số liên tiếp:
SELECT myid/100000 AS block, count(*) AS total FROM mytable GROUP BY myid/100000;
Điều này trả về khoảng 3500 hàng.
Tôi nhận thấy rằng sự tồn tại của một chỉ mục nhất định tăng tốc đáng kể truy vấn này mặc dù kế hoạch truy vấn hoàn toàn không đề cập đến nó. Kế hoạch truy vấn không có chỉ mục:
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)
Chỉ số:
db=> CREATE INDEX myindex ON mytable ((myid/100000));
db=> VACUUM ANALYZE;
Gói truy vấn mới:
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)
Vì vậy, các kế hoạch truy vấn và thời gian chạy khác nhau đáng kể (gần ba lần) nhưng không đề cập đến chỉ số. Hành vi này có thể tái tạo hoàn hảo trên máy dev của tôi: Tôi đã trải qua nhiều chu kỳ bỏ chỉ mục, kiểm tra truy vấn nhiều lần, tạo lại chỉ mục, một lần nữa kiểm tra truy vấn nhiều lần. Chuyện gì đang xảy ra ở đây vậy?
explain (analyze true, verbose true) ...
?
HashAggregate
phương thức (và không cần sắp xếp), do đó bạn sẽ có hiệu suất tốt hơn. Tại sao chỉ số không được đề cập trong kế hoạch, tôi không phải là một đầu mối.