Sql 在时间限制内获取COUNT()结果
PostgreSQL中是否有方法中止COUNT*语句的执行并返回其当前结果 我想参加:Sql 在时间限制内获取COUNT()结果,sql,postgresql,count,postgresql-performance,Sql,Postgresql,Count,Postgresql Performance,PostgreSQL中是否有方法中止COUNT*语句的执行并返回其当前结果 我想参加: SELECT COUNT(*) FROM table WHERE something=x; 有些查询几乎可以在短时间内完成,但有些查询需要相当长的时间。我希望: 若语句在时间限制内完成,则返回final 后果 否则它将中止执行,但返回当前结果。 无论它是完成执行还是中止,都可以获得退出状态 我找到了statement\u timeout设置,但它不返回任何结果,只是中止。我不相信在查询完成并使最终用户(也称
SELECT COUNT(*) FROM table WHERE something=x;
有些查询几乎可以在短时间内完成,但有些查询需要相当长的时间。我希望:
若语句在时间限制内完成,则返回final
后果
否则它将中止执行,但返回当前结果。
无论它是完成执行还是中止,都可以获得退出状态
我找到了statement\u timeout设置,但它不返回任何结果,只是中止。我不相信在查询完成并使最终用户(也称为您)看到结果集之前,您将永远不会得到带有计数的结果集。这就是ACID数据库的基本规则。在启动SELECT命令时,您要求获取当时行数的快照
您最好从另一个角度来看待这个问题,通过对查询执行解释,然后调查结果,来了解为什么某些查询需要很长时间。我相信,在查询完成并让最终用户(即您)看到之前,您永远不会得到带有计数的结果集。这就是ACID数据库的基本规则。在启动SELECT命令时,您要求获取当时行数的快照
你最好从另一个角度来看待这个问题,通过对查询进行解释,然后调查结果,来了解为什么有些查询需要很长时间。你可以很容易地指示Postgres计数到给定的限制-最大行数,而不是经过的时间:
SELECT count(*)
FROM (
SELECT 1 FROM tbl
WHERE something = 'x'
LIMIT 100000 -- stop counting at 100k
) sub;
如果计数需要很长时间,可能是因为您的表太大,或者是因为您的设置存在其他问题。无论哪种方式,估计的数量都足以满足您的目的:
在经过最长时间后,就其本身而言,不可能停止计数。您可以使用上述技术对计数进行分区,并在每个步骤后检查经过的时间。但这会增加很多开销。跳过带有偏移量的行并不比计算它们便宜多少。我想我不会用它。作为概念证明:
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进行分区…您可以轻松地指示Postgres计数到给定的限制-最大行数,而不是经过的时间:
SELECT count(*)
FROM (
SELECT 1 FROM tbl
WHERE something = 'x'
LIMIT 100000 -- stop counting at 100k
) sub;
如果计数需要很长时间,可能是因为您的表太大,或者是因为您的设置存在其他问题。无论哪种方式,估计的数量都足以满足您的目的:
在经过最长时间后,就其本身而言,不可能停止计数。您可以使用上述技术对计数进行分区,并在每个步骤后检查经过的时间。但这会增加很多开销。跳过带有偏移量的行并不比计算它们便宜多少。我想我不会用它。作为概念证明:
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进行分区…感谢您回答和编辑此问题。对不起我的英语:我想,count需要一些时间,因为它必须加入所有其他表。我放弃了这个想法,用规范化换取了性能。@Dmitry:通常,您可以同时拥有:规范化和性能。A可能会有帮助。感谢您回答和编辑此问题。对不起我的英语:我想,count需要一些时间,因为它必须加入所有其他表。我放弃了这个想法,用规范化换取了性能。@Dmitry:通常,您可以同时拥有:规范化和性能。A可能会有帮助。