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


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

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


12064
2017-12-17 21:24


起源

对于count(*)vs count(其他),看看(这里)[stackoverflow.com/questions/4437399/... - Ronnis


答案:


最好的方法是确保你跑步 SELECT COUNT 在一个列上(SELECT COUNT(*) 比较慢 - 但是 SELECT COUNT 永远是获取事物数量的最快方式(数据库在内部优化查询)。

如果您查看下面的评论,您可以查看原因的论据 SELECT COUNT(1) 可能是你最好的选择。


13
2017-12-17 21:26



如果在表上索引的列上选择count(columnName),则会更好。 - DwB
所以不是SELECT COUNT(1)而是SELECT COUNT(id)? - tofutim
@Luke,@ dwb:你能证明吗? COUNT(1)与COUNT(X)相同(按照 文档)因为1不是null。 COUNT(*)是一样的。它会选择任何索引。 - gbn
SELECT COUNT() 才不是 意思是“计算所有列”。这意味着计算任何一行。它在语义上与SELECT COUNT(任何非NULL常量值)相同。它与SELECT *无关。 - Larry Lustig
这是错的。 SELECT COUNT(列)不提供与SELECT COUNT(非NULL常量)相同的优化可能性。在后一种情况下,不需要进行表或索引扫描;返回主键索引中的行数或条目数就足够了。 - Larry Lustig


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


1
2018-01-06 08:10





我不相信你会找到一个特殊的方法。但是,您可以对主键进行选择计数,使其更快一些。


0
2017-12-17 21:29





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

没错,任何类型的查询

SELECT COUNT(非NULL常量值)FROM表

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

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


0
2017-12-17 21:45





如果您确定(非常确定)您从未删除该表中的任何行,并且尚未使用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是并且将始终是连续的数字。


0
2017-12-01 10:32



在这里,您可以阅读有关依赖于rowid的内容 链接 - Teolazza


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

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

它的效率比 select Count(1) from 'table_name'(不包括单引号)

sp_spaceused 可以用于任何表,当表格特别大(数亿行)时,它非常有用,返回行数,而 'select Count(1)' 可能需要10秒以上。而且,它不需要考虑任何列名/密钥字段。


-1
2017-10-13 19:12



问题是关于SQLite,而不是SQL Server - dsz