【发布时间】: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