我在尝试查找表中的记录总数时遇到(在我看来)奇怪的性能问题。 (简化)表格如下所示:
CREATE TABLE "records" (
pk INTEGER PRIMARY KEY AUTOINCREMENT,
other_table_fk INTEGER,
int_value INTEGER,
FOREIGN KEY(other_table_fk) REFERENCES other_table(pk)
ON DELETE CASCADE
}
CREATE INDEX int_value_idx ON records(int_value);
现在,当我尝试查询所有记录的计数时,这需要很长时间:
$ time sqlite3 db.sqlite "SELECT count(ROWID) FROM records"
100000
real 0m2.962s
user 0m0.162s
sys 0m2.618s
使用索引字段时,查询速度更快(但计数相同):
$ time sqlite3 db.sqlite "SELECT count(ROWID) FROM records WHERE records.int_value > 0"
100000
real 0m0.083s
user 0m0.015s
sys 0m0.057s
我的问题是,表模式依赖于用户配置,因此我无法确定表中是否有索引字段,但我仍然希望获得索引COUNT
的性能。
我知道主键有自己的索引,但在这种情况下,这似乎没有帮助:
$ time sqlite3 db.sqlite "SELECT count(ROWID) FROM records WHERE records.pk > 0"
100000
real 0m2.965s
user 0m0.138s
sys 0m2.636s
奇怪的是,即使如果我在主键上创建了一个额外的索引,这也无济于事:
$ time sqlite3 db.sqlite "CREATE INDEX records_pk_idx ON records(pk)"
real 0m3.288s
user 0m0.313s
sys 0m2.812s
$ time sqlite3 db.sqlite "SELECT count(ROWID) FROM records WHERE records.pk > 0"
100000
real 0m2.974s
user 0m0.154s
sys 0m2.624s
我通过使用MAX(_ROWID_)
(不是选项,因为我经常删除)和使用triggers to store the number of records(似乎"脏"对我来说)来阅读避免此问题的建议存储冗余信息)。
还有其他方法可以加快这些看似微不足道的疑问吗?
记录:
$ sqlite3 -version
3.6.20
我坚持使用这个版本。
编辑:
根据CL.建议EXPLAIN QUERY PLAN
信息:
$ sqlite3 db.sqlite "EXPLAIN QUERY PLAN SELECT count(ROWID) FROM records"
0|0|TABLE records
$ sqlite3 db.sqlite "EXPLAIN QUERY PLAN SELECT count(ROWID) FROM records WHERE records.pk < 0"
0|0|TABLE records USING PRIMARY KEY
$ sqlite3 db.sqlite "EXPLAIN QUERY PLAN SELECT count(ROWID) FROM records WHERE records. int_value > 0"
0|0|TABLE records WITH INDEX int_value_idx
这似乎没有添加任何其他信息。