我正在寻找计算大型(1500万行)表中有多少行的最佳方法。根据我在此事上发现的一些较旧的帖子,select count(*) from table;
的天真方式显然是O(n),例如http://osdir.com/ml/sqlite-users/2010-07/msg00437.html
是否有一个恒定的时间机制来获取此信息,或者是否存在直接select count(*)
查询的首选替代方法?
答案 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(*)
相同的时间,但它会为您缓存结果(以及其他一些统计信息)。