在SQLite中是count(*)的常量时间,如果没有,那么什么是替代方案?

时间:2013-09-14 23:13:12

标签: sql sqlite count

我正在寻找计算大型(1500万行)表中有多少行的最佳方法。根据我在此事上发现的一些较旧的帖子,select count(*) from table;的天真方式显然是O(n),例如http://osdir.com/ml/sqlite-users/2010-07/msg00437.html

是否有一个恒定的时间机制来获取此信息,或者是否存在直接select count(*)查询的首选替代方法?

6 个答案:

答案 0 :(得分:4)

SQLite对COUNT(*)进行了特殊优化,没有WHERE子句,它通过表的B树页面计算条目而不实际加载记录。 但是,这仍然要求访问所有表的数据(大型记录的溢出页除外),因此运行时仍为O(n)。

SQLite不会在数据库中存储单独的记录计数,因为这会使所有更改变慢。

答案 1 :(得分:2)

作为一种解决方法,您可以查询ROWID。如果你不从表中删除它将是准确的,否则它会很高

select max(rowid) from table

答案 2 :(得分:2)

不,这不是一直的时间。

sqlite> CREATE TABLE test ( a );
sqlite> EXPLAIN QUERY PLAN SELECT COUNT(*) FROM test;
0|0|0|SCAN TABLE test (~1000000 rows)
sqlite> EXPLAIN QUERY PLAN SELECT COUNT(1) FROM test;
0|0|0|SCAN TABLE test (~1000000 rows)

您可以使用EXPLAIN QUERY PLAN SELECT ...来了解查询的效果。

答案 3 :(得分:1)

这是一个很好的问题。我希望有一个包含表格的SQLite目录'行数。 select count(*) from table;是你最好的选择O(n)。与select count(1) from table;相比,您可以查看count(*)的效果。我推测两个count(1) and count( * )都会给你相似的速度。不幸的是,在SQLite中,没有任何替代计数(*)来获取行数。

另一方面,SQL Server有sys.dm_db_partition_stats that can be really helpful

答案 4 :(得分:1)

虽然同意其他答案并非恒定时间,但select count(*)的一个有趣且非显而易见的性能改进是如果您没有则添加索引。这可以在任意列上,并且在我的系统上将查询时间减少75%(ish)。

sqlite> select count(*) from TestTable;
15035000
CPU Time: user 0.468003 sys 4.368028

sqlite> select count(*) from TestTable;
15035000
CPU Time: user 0.561604 sys 4.290027

sqlite> select count(*) from TestTable;
15035000
CPU Time: user 0.483603 sys 4.368028

sqlite> explain query plan select count(*) from TestTable;
0|0|0|SCAN TABLE TestTable (~1000000 rows)

sqlite> create index test_index on TestTable(Pointer);

sqlite> select count(*) from TestTable;
15035000
CPU Time: user 0.062400 sys 0.780005

sqlite> select count(*) from TestTable;
15035000
CPU Time: user 0.187201 sys 0.655204

sqlite> select count(*) from TestTable;
15035000
CPU Time: user 0.140401 sys 0.748805

sqlite> explain query plan select count(*) from TestTable;
0|0|0|SCAN TABLE TestTable USING COVERING INDEX test_index(~1000000 rows)

答案 5 :(得分:0)

我相信您可以使用sqlite_stat1表在运行ANALYZE table后检索表格中的行数:

  

此列表中的第一个整数是索引和表中的行数。

此表中的统计信息不会随您的数据一起更新,因此随着表格的更改,它们会变得不那么准确。这有多大取决于您的用例。

ANALYZE可能需要与COUNT(*)相同的时间,但它会为您缓存结果(以及其他一些统计信息)。