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

在SQLite中统计表中的行最有效的方法是什么?,sql,sqlite,Sql,Sqlite,我总是使用“从X中选择计数(1)”,但这可能不是最有效的。有什么想法吗?其他选项包括SELECT COUNT(*),或者如果最后一个插入的id是自动递增的(并且从未删除),则可能获取该id 如果我只是想知道桌子上有没有什么东西呢?(例如,count>0?最好的方法是确保在单个列上运行SELECT count(SELECT count(*)较慢)-但是SELECT count始终是获取事物计数的最快方法(数据库在内部优化查询) 如果您查看下面的评论,您可以看到为什么SELECT COUNT(1)可

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


如果我只是想知道桌子上有没有什么东西呢?(例如,count>0?

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


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

我不相信您会找到一种特殊的方法来解决这个问题。但是,您可以在主键上执行select计数,使其快一点。

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

否则,任何类型的查询

从表中选择计数(非空常量值)

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


一旦在SELECT计数中引入一列,您就要求引擎至少执行一次索引扫描,可能还会执行一次表扫描,这将更慢。

sp\u spaceused'table\u name'
(不包括单引号)

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

它比从“表名”中选择计数(1)更有效。(不包括单引号)

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

< P>如果您确信(确实)从未删除该表中的任何行,并且表没有用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是并且将始终是连续的数字。

为了跟进girasquid的回答,作为一个数据点,我有一个包含230万行的SQLite表。使用表中的
选择count(*),对行进行计数花费了3秒多的时间。我还尝试使用
从表中选择rowid
(认为rowid是默认的主索引键),但速度并没有加快。然后,我在数据库中的一个字段上建立了一个索引(只是一个任意字段,但我选择了一个整数字段,因为我从过去的经验中知道,短字段上的索引可以非常快,我认为这是因为索引本身存储了一个值的副本)<代码>从表中选择my_short_字段
将时间缩短到不到一秒。

如果在表中索引的列上选择count(columnName),则效果更好。因此,不要选择count(1),而是选择count(id)?@Luke,@dwb:你能证明这一点吗?计数(1)与计数(X)(根据)相同,因为1不为空。计数(*)是相同的。它将选择任何索引。SELECT COUNT()并不表示“计算所有列”。它意味着数一数任何一行。它在语义上与SELECT COUNT(任何非空常量值)相同。它与SELECT*无关。这是错误的。SELECT COUNT(列)不提供与SELECT COUNT(非空常量)相同的优化可能性。在后一种情况下,不需要表或索引扫描;返回主键索引中的行数或条目数就足够了。对于count(*)vs count(其他内容),请看一看(此处)[问题是关于SQLite,而不是SQL Server这里您可以阅读一些关于依赖rowid的内容