sql - 为什么 SQLITE 在一个简单的计数查询上要花很长时间?

标签 sql database sqlite database-tuning

我有一组 SQLITE 表,磁盘上的大小总计为 7 GB。我正在查询的特定表 (FQ) 大约有 50 列和 300 万行。

我正在从 sqlite3 交互式 shell (sqlite3.exe) 进行查询。我正在运行的查询是:“select count(Date) from FQ;”。大约 300 万行需要 10 多分钟来计算。第一次之后,它似乎被缓存了,结果几乎是即时的。我正在一台具有 8 GB RAM 的 Windows 10 电脑上运行,没有运行其他任何东西。

日期是两个主键之一(日期和 ID)。有 360 个唯一日期和约 8-10k ID,表中每个日期/ID 组合都有一个条目。

以下是我已经完成的一些事情:

  1. 我在整个表格上有一个覆盖索引。
  2. 我已在此数据库上运行 ANALYZE。
  3. 当我执行“EXPLAIN QUERY PLAN”时,它表示正在使用覆盖索引进行表扫描(如预期的计数)。

简单扫描一个包含 300 万行的表怎么会花费这么长时间?

[编辑:我应该澄清,我对其他计数方式不感兴趣 - 我希望扫描不必那么慢(例如,使用 sum()+ 也很慢”分组依据")]

[更新:今天我尝试了另外两件事 - 首先我尝试使用“WITHOUT ROWID”,无论哪种方式结果都是相似的。然后我完全删除了所有表格的索引。现在,数百万行的计数在 4 秒内完成。既然所有索引都消失了,数据库文件自然就更小了(2 GB 与 7 GB),但这并不能解释 10 分钟到 4 秒的差异!是什么导致覆盖索引减慢表扫描速度?是否存在扫描索引速度较慢的情况,如果是这样,为什么 SQLITE 不直接扫描原始表本身?]

最佳答案

我终于找到问题所在了。在数据库上运行 VACUUM 命令解决了该问题。我已运行 .dbinfo 来确认 page_size 乘以页数总计大约等于文件大小。再加上我没有从数据库中删除任何内容(只是插入),我认为我不需要清理(或碎片整理)。

但看起来真空所做的重组也使计数查询的速度发生了巨大的变化(正如我在其他地方看到的报道,现在计数查询以毫秒为单位完成)。

关于sql - 为什么 SQLITE 在一个简单的计数查询上要花很长时间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62231466/

相关文章:

sql - 计算没有重叠的总时间

MySQL 查找结果是查询字符串的子字符串

sql-server - 如何使用 VBScript 从数据库复制到文本文件?

ios - 使用 FMDB Swift 创建多个表

sql - 按位或-SQLite中的意外结果

sql - 当相关数据需要存储在连接表中时,约定是什么?

java - MySQL 语法错误 |您的 SQL 语法有错误;

sql - impala sql 只选择特定长度的数字

mysql - 数据库设计:多表和外键

sqlite - 为什么 SQLite 事务绑定(bind)到硬盘轮换?