【问题标题】:postgresql statement_timeout behaviorpostgresql statement_timeout 行为
【发布时间】:2021-05-19 15:17:54
【问题描述】:

为了避免长时间运行的查询,我想为某些用户实现 statement_time。

pgdb=> alter user user1 set statement_timeout=600;
ALTER ROLE
pgdb=> select * from pg_user where usename = 'user1';
  usename  |  usesysid  | usecreatedb | usesuper | userepl | usebypassrls |  passwd  | valuntil |              useconfig
-----------+------------+-------------+----------+---------+--------------+----------+----------+--------------------------------------
 user1 | 2538084332 | f           | f        | f       | f            | ******** |          | {statement_timeout=600}
(1 row)

以 user1 身份登录 PSQL,运行非常短的查询返回,但大多数查询(将在几秒钟内完成,没有 statement_timeout 限制)即使 statement_timeout 设置为 180 秒也超时。

pgdb=> select count(*) from schema.tablea limit 10; -- huge table timeout
ERROR:  canceling statement due to statement timeout
Time: 184.118 ms
imaods=> explain select count(*) from schema.tablea limit 10;
                                                                                       QUERY PLAN

-------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------
 Limit  (cost=1906894.11..1906894.12 rows=1 width=8)
   ->  Finalize Aggregate  (cost=1906894.11..1906894.12 rows=1 width=8)
         ->  Gather  (cost=1906893.89..1906894.10 rows=2 width=8)
               Workers Planned: 2
               ->  Partial Aggregate  (cost=1905893.89..1905893.90 rows=1 width=8)
                     ->  Parallel Index Only Scan using idx1 on tablea  (cost=0.57..1828328.86 rows=31026013 width=0)
(6 rows)

pgdb=> select count(*) from tableb;
 count
-------
   260
(1 row)

Time: 0.672 ms
pgdb=> select count(*) from tableb a, tableb b;
 count
-------
 67600
(1 row)
Time: 4.405 ms

pgdb=> select count(*) from tableb a, tableb b, tableb c;  -- timeout
ERROR:  canceling statement due to statement timeout

pgdb=> explain select count(*) from tableb a, tableb b, tableb c;                                                                 
                                           QUERY PLAN
--------------------------------------------------------------------------------------------------------------
 Aggregate  (cost=264536.10..264536.11 rows=1 width=8)
   ->  Nested Loop  (cost=0.00..220596.10 rows=17576000 width=0)
         ->  Nested Loop  (cost=0.00..878.85 rows=67600 width=0)
               ->  Seq Scan on tableb a  (cost=0.00..16.60 rows=260 width=0)
               ->  Materialize  (cost=0.00..17.90 rows=260 width=0)
                     ->  Seq Scan on tableb b  (cost=0.00..16.60 rows=260 width=0)
         ->  Materialize  (cost=0.00..17.90 rows=260 width=0)
               ->  Seq Scan on tableb c  (cost=0.00..16.60 rows=260 width=0)
(8 rows)

pgdb=> explain analyze select count(*) from tableb a, tableb b, tableb c;
ERROR:  canceling statement due to statement timeout
pgdb=> explain select count(*) from tableb a, tableb b;
                                               QUERY PLAN
--------------------------------------------------------------------------------------------------------
 Aggregate  (cost=1047.85..1047.86 rows=1 width=8)
   ->  Nested Loop  (cost=0.00..878.85 rows=67600 width=0)
         ->  Seq Scan on tableb a  (cost=0.00..16.60 rows=260 width=0)
         ->  Materialize  (cost=0.00..17.90 rows=260 width=0)
               ->  Seq Scan on tableb b  (cost=0.00..16.60 rows=260 width=0)
(5 rows)

pgdb=> explain select count(*) from tableb;
                                        QUERY PLAN
------------------------------------------------------------------------------------------
 Aggregate  (cost=17.25..17.26 rows=1 width=8)
   ->  Seq Scan on tableb  (cost=0.00..16.60 rows=260 width=0)
(2 rows)

statement_timeout 是按估计时间还是按实际执行时间计算。按照解释计划,如果它认为它的估计时间超过 statement_timeout,它似乎考虑了估计时间并且不执行查询。这是预期的行为还是我错过了什么?我的理解是当实际执行时间超过超时限制时,它应该运行查询并超时。

【问题讨论】:

  • "即使 statement_timeout 设置为 180 秒。"不,它设置为 600 毫秒。到底是什么让你认为它设置为 180 年代?
  • 我玩的是不同的价值观,所以混在一起了。我在想它是秒,我应该是 rtfm,它的单位是毫秒。谢谢。

标签: postgresql


【解决方案1】:

不,它以实际执行时间为准。当语句开始执行时,计时器开始运行。否则你会如何解释你有 180 秒直到查询被取消?

PostgreSQL 不直接估计执行时间。成本测量有些人为,粗略的准则是 1 对应于在顺序扫描期间从磁盘读取一个 8kB 页面的时间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-04
    • 1970-01-01
    • 2020-09-21
    • 2021-12-03
    • 2022-08-04
    • 2021-12-22
    • 2014-07-28
    相关资源
    最近更新 更多