【问题标题】:is it ok to replace count(*) with count(1) in N1ql在 N1ql 中用 count(1) 替换 count(*) 可以吗
【发布时间】:2020-07-31 03:43:17
【问题描述】:

在某些情况下,我使用 n1ql 计算所有记录

Select count(*) from bucket where type='xyz' and column1='abc'.

这大约需要 25 秒,但如果我将其替换为 count(1) 则需要 19 秒。 我的问题是我们可以使用count(1) 而不是count(*)。我相信它只计算一列总数而不是全部计算。如果在 n1ql 中不是这种情况,请告诉我。

【问题讨论】:

  • 我认为没有任何可衡量的统计数据表明 count(1) 比 count() 更好,公平地说,我不是 couchbase 专家对此发表评论。然而,我记得在 Oracle 8i 之前有过这种讨论。一开始就不是真的!语义上,count() 是有意义的,它表示计算所有记录,count(1) 表示计算表中 1 的数量?
  • 这个问题你可以自己回答。结果是一样的吗?另见Why should I provide a Minimal Reproducible Example for a very simple SQL query?
  • count(1)count(*) 快是一个长期存在但仍然错误的神话。在您的情况下,第二次执行查询可能会从缓存中获取数据(由第一次查询填充)。
  • 您也可以尝试sum(1)进行比较。但我同意@a_horse_with_no_name - 即席计时只给出性能的指示,但为了增加它们的重要性,运行这两个查询几次以预热缓存,然后在安静的时间运行每个查询几次并使用中间值每个。

标签: sql couchbase n1ql


【解决方案1】:

如果您使用的是 CB 5.0 及更高版本,则 COUNT(*) 和 COUNT(1) 将被视为相同。

以下应该表现更好。

CREATE INDEX ix1 ON bucket(column1) WHERE type = "xyz";
SELECT COUNT(1) AS cnt
FROM bucket
WHERE type='xyz' AND column1='abc';

【讨论】:

    【解决方案2】:
    1. 关注count(1)。数据库引擎遍历整个表,但不从中获取值。服务器层每行放一个数字“1”返回,判断不能为空,逐行累加。

    2. 关注count(*)。它需要从磁盘读取数据,然后累积计数。数据库引擎将表中的总行数存储在磁盘上,因此执行 count(*) 将直接返回此行数。如果使用count(*),则不会取任何字段,也不会取任何值。因为它是按行累积的。该数据库已专门针对它进行了优化。

    3. 您也可以count(PRIMARY KEY Id)。数据库引擎返回的Id涉及解析数据行和复制字段值。

    4. 或者你也可以count(Field)。如果该“字段”定义为不为空,则从记录中逐行读取该字段,判断不能为空,逐行累加;如果这个“字段”定义允许为null,那么在执行的时候,判断有可能为null,我们需要取出值重新判断,不为null就累加。

    最后,我们来整理一下效率:
    count(*)>=count(1)>count(id)>count(field)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-27
      • 2020-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-12
      相关资源
      最近更新 更多