Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/78.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 在时间限制内获取COUNT()结果_Sql_Postgresql_Count_Postgresql Performance - Fatal编程技术网

Sql 在时间限制内获取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设置,但它不返回任何结果,只是中止。我不相信在查询完成并使最终用户(也称

PostgreSQL中是否有方法中止COUNT*语句的执行并返回其当前结果

我想参加:

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可能会有帮助。