在SQLite中计算表中行的最有效方法是什么?

tof*_*tim 14 sql sqlite

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

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

gir*_*uid 12

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

如果你查看下面的评论,你可以看到为什么SELECT COUNT(1)可能是你最好的选择.

  • 我刚刚在我的数据库上检查过它,在我的例子中,“count(*)”的运行速度比“count(1)”快 4 倍,比“count(indexed_column)”快 7 倍。所以答案是不正确的......我使用 sqlite 3.31.1 (8认同)
  • @Luke,@ dwb:你能证明吗?COUNT(1)与COUNT(X)相同(根据[docs](http://www.sqlite.org/lang_aggfunc.html)),因为1不为null.COUNT(*)是相同的.它会选择任何索引. (6认同)
  • SELECT COUNT(*)确实*不*表示"计算所有列".这意味着计算任何一行.它在语义上与SELECT COUNT(任何非NULL常量值)相同.它与SELECT*无关. (2认同)
  • 这是错误的。SELECT COUNT(column) 不提供与 SELECT COUNT(non-NULL Constant) 相同的优化可能性。在后一种情况下,不需要表或索引扫描;返回主键索引中的行数或条目数就足够了。 (2认同)

M K*_*atz 8

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


Teo*_*zza 6

如果您确定(真正确定)从未从该表中删除任何行,并且您的表尚未使用WITHOUT ROWID 优化进行定义,您可以通过调用以下命令来获取行数:

select max(RowId) from table;
Run Code Online (Sandbox Code Playgroud)

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

select MaxRowId - MinRowId + 1 from
  (select max(RowId) as MaxRowId from table) JOIN
  (select min(RowId) as MinRowId from table);
Run Code Online (Sandbox Code Playgroud)

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