优化PostgreSQL中的窗口函数以使用索引
我在PostgreSQL 9.2 DB中有一个表,创建并填充如下:
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) 正如预期的那样,排序占用了大部分查询执行时间,使用索引肯定会有所帮助. 所以我创建了CREATE INDEX ON foo(id,date)并期望现在它将使用索引.但事实并非如此.我与外部合并有相同的计划,甚至关闭顺序扫描也没用.我刚刚结束了位图索引扫描 -> 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) 题 解决方法
要匹配您创建的索引:
CREATE INDEX ON foo(id,date) 你必须这样做: ROW_NUMBER() OVER (PARTITION BY id ORDER BY date DESC NULLS LAST) 这是ASC完美的逆序. 除此之外,您可以运行: SELECT DISTINCT ON (id) id,date FROM foo ORDER BY id,date DESC NULLS LAST; 但那可能不是你想问的问题.无论哪种方式,我都会制作索引: CREATE INDEX ON foo(id,date DESC NULLS LAST) 这样max(date)是每个id的第一个索引条目. > PostgreSQL sort by datetime asc,null first? (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |