我有一组sqlite表,在磁盘上加起来有7GB。我正在查询的特定表(fq)大约有50列和300万行。
我从sqlite3交互式shell(sqlite3.exe)进行查询。我正在运行的查询是:“select count(date)from fq;”。大约300万行需要10分钟以上的时间来计算。第一次之后,它似乎被缓存了,结果几乎是即时的。我在一台Windows10PC上运行,内存为8GB,其他什么都不运行。
日期是两个主键之一(它是date和id)。有360个唯一的日期和~8-10k id,表中每个日期/id组合有一个条目。
以下是我已经做过的一些事情:
我在整张table上都有一个索引。
我已经对这个数据库进行了分析。
当我执行“解释查询计划”时,它说它正在使用覆盖索引进行表扫描(正如计数所预期的那样)。
对一个300万行的表进行简单的扫描怎么可能需要这么长时间?
[编辑:我应该澄清一下,我对其他计数方法不感兴趣-我希望扫描不必这么慢(例如,使用sum()+“group by”)时也很慢]
[更新:今天我尝试了另外两件事-首先我尝试使用“without rowid”,结果两种方式都很相似。然后我删除了所有表的索引。现在几百万行的计数在4秒内完成。现在所有的索引都没有了,数据库文件自然就变小了(2GB对7GB),但这不应该解释10分钟到4秒的差别!是什么使覆盖索引减慢了表扫描的速度?是否存在扫描索引速度较慢的情况,如果是,为什么sqlite不扫描原始表本身?]
1条答案
按热度按时间41zrol4v1#
我终于解决了问题。在数据库上运行vacuum命令解决了这个问题。我已经运行了.dbinfo来确认页面大小乘以页面数量加起来大约等于文件大小。再加上我没有从数据库中删除任何内容(只插入),这让我认为我不需要抽真空(或去碎片)。
但是vacuum的重新组织似乎也对count查询的速度产生了巨大的影响(正如我在其他地方看到的那样,它现在以毫秒完成)。