【问题标题】:Postgres window function calculate order?Postgres窗口函数计算顺序?
【发布时间】:2018-07-23 22:46:35
【问题描述】:

数据分页有两种实现方式。

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';

性能差异很大,似乎第二个使用大量时间来计算 count(*) over ()。 我猜Postgres首先为每一行计算total,然后限制结果,而不是在子查询(第一个)中,它首先限制然后计算子查询?

【问题讨论】:

  • 限制在最后,但在计划时会在执行之前考虑

标签: postgresql


【解决方案1】:

我测试了 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 毫秒用于处理窗口函数,这是执行时间的最大份额。

窗口函数是在结果集生成后计算的,所以这并不奇怪。

【讨论】:

    猜你喜欢
    • 2019-04-07
    • 1970-01-01
    • 2014-09-26
    • 2016-10-23
    • 1970-01-01
    • 1970-01-01
    • 2021-03-01
    • 1970-01-01
    • 2021-12-07
    相关资源
    最近更新 更多