【问题标题】:What is the most efficient way to count rows in a table in SQLite?在 SQLite 中对表中的行进行计数的最有效方法是什么?
【发布时间】:2010-12-17 21:24:59
【问题描述】:

我一直只使用“SELECT COUNT(1) FROM X”,但也许这不是最有效的。有什么想法吗?其他选项包括 SELECT COUNT(*) 或者如果它是自动递增的(并且从不删除),则可能获取最后插入的 id。

如果我只是想知道桌子上是否有任何东西呢? (例如,计数 > 0?)

【问题讨论】:

  • 对于 count(*) 与 count(其他),看看 (这里) [stackoverflow.com/questions/4437399/…
  • expo-sqlite-orm 旁注 - 这与 OP 无关,但我在查找 count 不起作用的原因时发现了这一点 - 这是因为库正在按定义的模型列过滤所有结果(甚至计数),解决方法是使用已知列的别名,例如SELECT COUNT(X) as id 如果您的模型上有 id 列。

标签: sql sqlite


【解决方案1】:

最好的方法是确保在单个列上运行 SELECT COUNTSELECT COUNT(*) 较慢) - 但 SELECT COUNT 始终是获​​取事物计数的最快方法(数据库优化查询内部)。

如果您查看下面的 cmets,您会看到为什么 SELECT COUNT(1) 可能是您的最佳选择。

【讨论】:

  • 如果在表中索引的列上选择 count(columnName) 会更好。
  • @Luke, @dwb:你能证明这一点吗? COUNT(1) 与 COUNT(X) 相同(根据docs),因为 1 不为空。 COUNT(*) 是一样的。它将选择任何索引。
  • SELECT COUNT() *not 表示“计算所有列”。这意味着计算任何行。它在语义上与 SELECT COUNT(任何非 NULL 常量值)相同。它与 SELECT * 无关。
  • 这是错误的。 SELECT COUNT(column) 不提供与 SELECT COUNT(non-NULL 常量) 相同的优化可能性。在后一种情况下,不需要表或索引扫描;返回主键索引中的行数或条目数就足够了。
  • 我刚刚在我的数据库上检查了它,count(*) 的工作速度比 count(1) 快 4 倍,比 count(indexed_column) 快 7 倍。所以答案是不正确的......我使用 sqlite 3.31.1
【解决方案2】:

为了跟进 girasquid 的回答,作为数据点,我有一个包含 230 万行的 sqlite 表。使用select count(*) from table,计算行数需要超过 3 秒。我也尝试使用SELECT rowid FROM table,(认为rowid 是默认的主索引键),但这并没有更快。然后我对数据库中的一个字段进行了索引(只是一个任意字段,但是我选择了一个整数字段,因为我从过去的经验中知道短字段上的索引可以非常快,我认为是因为索引存储了一个副本索引本身的值)。 SELECT my_short_field FROM table 将时间缩短到不到一秒。

【讨论】:

    【解决方案3】:

    如果您确定(非常确定)您从未从该表中删除任何行,并且您的表尚未使用 WITHOUT ROWID 优化定义,您可以通过调用获得行数:

    select max(RowId) from table;
    

    或者如果你的表是一个循环队列,你可以使用类似的东西

    select MaxRowId - MinRowId + 1 from
      (select max(RowId) as MaxRowId from table) JOIN
      (select min(RowId) as MinRowId from table);
    

    这确实非常快(毫秒),但您必须注意,因为 sqlite 表示行 id 在同一个表的所有行中是唯一的。 SQLite 没有声明行 id 是并且将始终是连续的数字。

    【讨论】:

    • 这里你可以读到一些关于依赖rowid link
    【解决方案4】:

    我不相信您会为此找到特殊的方法。但是,您可以对主键进行选择计数以加快速度。

    【讨论】:

      【解决方案5】:

      获取行数的最快方法是直接从表元数据(如果有)。不幸的是,我在 SQLite 中找不到此类数据的参考。

      否则,任何类型的查询

      SELECT COUNT(non-NULL constant value) FROM table

      应该优化以避免需要对表,甚至是索引进行扫描。理想情况下,引擎将简单地从内部元数据返回表中已知的当前行数。如果做不到这一点,它只需要知道任何非 NULL 列的索引中的条目数(主键索引是第一个查找的位置)。

      将列引入 SELECT COUNT 后,您就要求引擎至少执行一次索引扫描,也可能执行一次表扫描,这样会更慢。

      【讨论】:

        【解决方案6】:

        sp_spaceused 'table_name'(不包括单引号)

        这将返回上表中的行数,这是我遇到的最有效的方法。

        select Count(1) from 'table_name'更高效(不包括单引号)

        sp_spaceused 可以用于任何表,当表非常大(数亿行)时,它非常有用,可以正确返回行数,而'select Count(1)' 可能需要超过 10 秒。此外,它不需要考虑任何列名/关键字段。

        【讨论】:

        • 问题是关于 SQLite,而不是 SQL Server
        猜你喜欢
        • 1970-01-01
        • 2011-07-13
        • 1970-01-01
        • 2013-01-23
        • 1970-01-01
        • 2017-06-13
        • 2010-11-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多