我有一個表中的PostgreSQL 9.2數據庫,創建並填寫如下:優化窗函數的使用指數
CREATE TABLE foo(id integer, date date);
INSERT INTO foo
SELECT (id % 10) + 1, now() - (id % 50) * interval '1 day'
FROM generate_series(1, 100000) AS id;
現在,我需要找到所有對(id, date)
使得日期是最大所有配對中的一個與id
相同。查詢是一種衆所周知的,它通常使用所謂的ROW_NUMBER()
SELECT id, date
FROM (
SELECT id, date, ROW_NUMBER() OVER (PARTITION BY id ORDER BY date DESC) rn
FROM foo
) sbt
WHERE sbt.rn = 1;
現在,我問該查詢的計劃,並計算出該WindowAgg
節點需要一個表來先排序的窗函數。
Subquery Scan on sbt (cost=11116.32..14366.32 rows=500 width=8) (actual time=71.650..127.809 rows=10 loops=1)
Filter: (sbt.rn = 1)
Rows Removed by Filter: 99990
-> WindowAgg (cost=11116.32..13116.32 rows=100000 width=8) (actual time=71.644..122.476 rows=100000 loops=1)
-> Sort (cost=11116.32..11366.32 rows=100000 width=8) (actual time=71.637..92.081 rows=100000 loops=1)
Sort Key: foo.id, foo.date
Sort Method: external merge Disk: 1752kB
-> Seq Scan on foo (cost=0.00..1443.00 rows=100000 width=8) (actual time=0.006..6.138 rows=100000 loops=1)
正如所料,分揀了多數人的查詢執行時間,它肯定會有助於使用index
ES。
因此,我創建CREATE INDEX ON foo(id, date)
,並期望現在它將使用索引。但事實並非如此。我得到了與external merge
相同的計劃,甚至關掉sequential scan
也沒用。我剛剛結束了Bitmap Index Scan
-> Sort (cost=12745.58..12995.58 rows=100000 width=8) (actual time=69.247..90.003 rows=100000 loops=1)
Sort Key: foo.id, foo.date
Sort Method: external merge Disk: 1752kB
-> Bitmap Heap Scan on foo (cost=1629.26..3072.26 rows=100000 width=8) (actual time=5.359..12.639 rows=100000 loops=1)
-> Bitmap Index Scan on foo_id_date_idx (cost=0.00..1604.26 rows=100000 width=0) (actual time=5.299..5.299 rows=100000 loops=1)
問題
可以WindowAgg
用不完的指標進行排序?我認爲它不能不明白爲什麼... GroupAggreagte
s可以和它提供良好的性能改善。
你的排序發生在磁盤上。嘗試增加會話的'work_mem'並查看是否改善了事情 –
@a_horse_with_no_name是的,我知道改善'work_mem'會將排序算法切換到快速排序,如果內存足夠用的話。但爲什麼我們不能使用'foo(id,date)'上的索引和窗口函數一起提供的排序呢?與聚合我們可以。 –