【发布时间】:2014-09-06 21:25:39
【问题描述】:
查询 A 在微秒内执行:
SELECT t1.id
FROM (SELECT t0.id AS id FROM t0) AS t1
WHERE NOT (EXISTS (SELECT 1
FROM t2
WHERE t2.ph_id = t1.id AND t2.me_id = 1 AND t2.rt_id = 4))
LIMIT 20 OFFSET 0
但查询 B 大约需要 25 秒:
SELECT t1.id, count(*) OVER () AS count
FROM (SELECT t0.id AS id FROM t0) AS t1
WHERE NOT (EXISTS (SELECT 1
FROM t2
WHERE t2.ph_id = t1.id AND t2.me_id = 1 AND t2.rt_id = 4))
LIMIT 20 OFFSET 0
(区别只是select子句中的一项——一个窗口聚合)
EXPLAIN 输出如下,对于 A:
Limit (cost=0.00..1.20 rows=20 width=4)
-> Nested Loop Anti Join (cost=0.00..3449.22 rows=57287 width=4)
Join Filter: (t2.ph_id = t0.id)
-> Seq Scan on t0 (cost=0.00..1323.88 rows=57288 width=4)
-> Materialize (cost=0.00..1266.02 rows=1 width=4)
-> Seq Scan on t2 (cost=0.00..1266.01 rows=1 width=4)
Filter: ((me_id = 1) AND (rt_id = 4))
对于 B:
Limit (cost=0.00..1.45 rows=20 width=4)
-> WindowAgg (cost=0.00..4165.31 rows=57287 width=4)
-> Nested Loop Anti Join (cost=0.00..3449.22 rows=57287 width=4)
Join Filter: (t2.ph_id = t0.id)
-> Seq Scan on t0 (cost=0.00..1323.88 rows=57288 width=4)
-> Materialize (cost=0.00..1266.02 rows=1 width=4)
-> Seq Scan on t2 (cost=0.00..1266.01 rows=1 width=4)
Filter: ((me_id = 1) AND (rt_id = 4))
为了构建分页 UI,我正在添加窗口聚合以获取 LIMITing 之前的总行数。
【问题讨论】:
标签: sql performance postgresql window-functions