sql - 为什么 SQLITE 永远在一个简单的计数查询上?
问题描述
我有一组 SQLITE 表,在磁盘上加起来高达 7 GB。我正在查询的特定表 (FQ) 大约有 50 列和 300 万行。
我正在从 sqlite3 交互式 shell (sqlite3.exe) 进行查询。我正在运行的查询是:“从 FQ 中选择计数(日期);”。大约 300 万行需要10 多分钟来计算。第一次之后,它似乎被缓存了,结果几乎是即时的。我在具有 8 GB RAM 的 Windows 10 PC 上运行,没有其他任何东西在运行。
日期是两个主键之一(日期和 ID)。有 360 个唯一日期和大约 8-10k 个 ID,并且该表对于每个日期/ID 组合都有一个条目。
以下是我已经做过的一些事情:
- 我在整个表上有一个覆盖索引。
- 我已经在这个数据库上运行了 ANALYZE。
- 当我执行“EXPLAIN QUERY PLAN”时,它说它正在使用覆盖索引进行表扫描(如预期的那样)。
对一个包含 300 万行的表的简单扫描怎么会花费这么长时间?
[编辑:我应该澄清我对其他计数方式不感兴趣 - 我希望扫描不必那么慢(它也很慢,例如,使用 sum()+"group by" )]
[更新:今天我尝试了另外两件事——首先我尝试使用“WITHOUT ROWID”,结果都相似。然后我完全删除了所有表的索引。现在几百万行的计数在4 秒内完成。现在所有索引都消失了,数据库文件自然更小(2 GB 对 7 GB),但这不能解释 10 分钟到 4 秒的差异!是什么让覆盖索引减慢了表扫描速度?是否存在扫描索引较慢的地方,如果是,为什么 SQLITE 不只扫描原始表本身?]
解决方案
我终于弄清楚了问题所在。在数据库上运行VACUUM命令解决了这个问题。我已经运行 .dbinfo 来确认 page_size 乘以页数加起来大约是文件大小。再加上我没有从数据库中删除任何内容(仅插入),这让我认为我不需要清理(或碎片整理)。
但看起来,vacuum 所做的重组也对计数查询的速度产生了巨大的影响(正如我在其他地方看到的那样,现在以毫秒为单位完成)。
推荐阅读
- .htaccess - 使用 htaccess 将 URL php 重写为 html?
- azure-blob-storage - Databricks read Azure blob last modified date
- php - How to hook into a pages title to filter it in wordpress
- android - Cannot add Floating Action Button - cannot inflate
- python - 如何在 Python 中将字符串字节转换为字节
- google-signin - Find Google OAuth2 clientId and Secret
- android - Should I handle a lot of UI on one screen with fragments? [android]
- javascript - Canvas - how to draw line from click to click and change colour on new "route"
- python - What do "Blas GEMM launch failed" errors from Tensorflow mean?
- makefile - Define custom gmake function equivalent to multiple piped functions