Postgres window function calculate order?

时间:2018-07-23 14:14:59

标签: postgresql

There are two implementation for data paginate.

SELECT
  (SELECT count(*) FROM (SELECT * FROM "items") m) :: INT AS total,
  "t".*
FROM (SELECT *
      FROM "items") AS "t"
LIMIT '10';

Select count("t".*) over () as total, "t".*
FROM (SELECT *
      FROM "items") AS "t"
LIMIT '10';

the performance is huge different, and it seems the second one use lots of time to calculate count(*) over (). I guess Postgres calculate total for every row first, then limit on result, instead of in subquery(first one), it do limit first and then calculate the sub-query?

1 个答案:

答案 0 :(得分:0)

我测试了1000000行,并且您的两个查询的执行计划确认了您的描述:

没有窗口功能:

                                                              QUERY PLAN                                                               
---------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=17906.01..17906.19 rows=10 width=15) (actual time=348.125..348.132 rows=10 loops=1)
   Buffers: shared hit=5407
   InitPlan 1 (returns $0)
    ->  Aggregate  (cost=17906.00..17906.01 rows=1 width=8) (actual time=348.081..348.081 rows=1 loops=1)
           Buffers: shared hit=5406
           ->  Seq Scan on items items_1  (cost=0.00..15406.00 rows=1000000 width=0) (actual time=0.015..166.658 rows=1000000 loops=1)
                 Buffers: shared hit=5406
   ->  Seq Scan on items  (cost=0.00..17906.00 rows=1000000 width=15) (actual time=348.122..348.127 rows=10 loops=1)
         Buffers: shared hit=5407
 Planning time: 0.386 ms
 Execution time: 348.252 ms
(11 rows)

具有窗口功能:

                                                          QUERY PLAN                                                          
------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=0.00..0.28 rows=10 width=19) (actual time=980.923..980.941 rows=10 loops=1)
   Buffers: shared hit=5406, temp read=2374 written=2564
   ->  WindowAgg  (cost=0.00..27906.00 rows=1000000 width=19) (actual time=980.920..980.935 rows=10 loops=1)
         Buffers: shared hit=5406, temp read=2374 written=2564
         ->  Seq Scan on items  (cost=0.00..15406.00 rows=1000000 width=11) (actual time=0.041..169.046 rows=1000000 loops=1)
               Buffers: shared hit=5406
 Planning time: 0.228 ms
 Execution time: 986.896 ms
(8 rows)

花费700毫秒来处理窗口函数,这是执行时间的主要部分。

窗口函数是在结果集生成之后计算出来的,因此这并不奇怪。