PostgreSQL中是否有办法中止COUNT(*)
语句的执行并返回其当前结果?
我想跑:
SELECT COUNT(*) FROM table WHERE something=x;
有些查询几乎没有时间完成,但有些查询需要花费很多时间。我想:
获得退出状态也是很好的(无论是完成执行还是中止)。
我找到statement_timeout
设置,但它不返回任何结果,只是中止。
答案 0 :(得分:0)
我不相信您会在查询完成之前获得带有计数的结果集,并使其对最终用户(即您)可见。这是ACID数据库基本规则的方式。从启动SELECT命令开始,您要求提供当时行数的快照。
从另一个角度查看问题可能会更好,并通过对查询执行EXPLAIN然后调查结果来查看为什么某些查询需要很长时间。
答案 1 :(得分:0)
您可以轻松指示Postgres计算到给定的LIMIT
- 最大行数,而不是已用时间:
SELECT count(*)
FROM (
SELECT 1 FROM tbl
WHERE something = 'x'
LIMIT 100000 -- stop counting at 100k
) sub;
如果count()
需要很长时间,您可能会有巨大的表或其他一些设置问题。无论哪种方式,估计计数都足以满足您的目的:
本身不可能在最长经过时间后停止计数。您可以 使用上述技术对计数进行分区,并检查每个步骤后的经过时间。但这会增加很多的开销。使用OFFSET
跳过行并不比计算它们便宜得多。我不认为我会用它。正如概念证明:
DO
$do$
DECLARE
_partition bigint := 100000; -- size of count partition
_timeout timestamptz := clock_timestamp() + interval '1s'; -- max time allowed
_round int := 0;
_round_ct bigint;
BEGIN
LOOP
SELECT count(*)
FROM (
SELECT 1 FROM tbl
WHERE something = 'x'
LIMIT _partition
OFFSET _partition * _round
) sub
INTO _round_ct;
IF _round_ct < _partition THEN
RAISE NOTICE 'count: %; status: complete', _partition * _round + _round_ct;
RETURN;
ELSIF clock_timestamp() > _timeout THEN
RAISE NOTICE 'count: %; status: timeout', _partition * _round + _round_ct;
RETURN;
END IF;
_round := _round + 1;
END LOOP;
END
$do$;
您可以将其包装在plpgsql函数中并传递参数。甚至使其适用于任何给定的表/列EXECUTE
...
如果您的ID列间隙很小,那么该技术会更有意义。您可以通过ID进行分区,但开销更少......