优化所有记录的 SQLite 读取

optimize SQLite read of all records

本文关键字:SQLite 读取 记录 优化      更新时间:2023-10-16

问题摘要

我可以非常快速地从单列表的单列中读取所有值。如何从具有其他几列的表中的单列中快速读取所有值?

我正在使用 C++ api 读取一个包含 220 万条记录的单个表的 sqlite 数据库。

数据有一个"坐标"列和(可选)其他几个列。"坐标"列是一个 BLOB,当前长度始终为 8 个字节。其他列是 TEXT 和 REAL 的混合,TEXT 字符串从几个字符到大约 100 个字符不等(长度因记录而异)。

在一个实验中,我创建了带有"坐标"列的表,以及大约 15 个其他列。数据库文件的总大小为 745 MB。我做了一个简单的

int rc = sqlite3_exec( db, "select coordinates from facilities", ReadSQLiteCallback, NULL, &errorMessage );

执行需要 91 秒。

然后,我创建了仅包含"坐标"列而没有其他数据列的表。数据库文件的总大小为 36 MB。我运行了相同的选择语句,花了 1.23 秒。

我试图了解导致这种速度巨大差异的原因,以及当表具有这些额外的数据列时如何提高速度。

我确实理解更大的文件意味着更多的数据需要阅读。但我预计速度减慢在最坏的情况下或多或少与文件大小成线性关系(即,可能需要 20 倍于 1.23 秒,或大约 25 秒,但不是 91 秒)。

问题第一部分

我没有在文件上使用索引,因为一般来说,我倾向于一次读取整个"坐标"列的大部分或全部,就像上面的简单选择一样。所以我真的不需要索引来排序或快速访问记录的子集。但是,也许拥有索引可以帮助引擎在读取所有数据时更快地从一个可变大小的记录移动到下一个记录?

有没有其他简单的想法可以帮助减少这 91 秒?

问题第二部分

假设没有灵丹妙药可以将 91 秒(当包括其他 15 个数据列时)降低到接近单个表中的 1.23 秒(当仅存在坐标列时),似乎我可以只使用多个表,将坐标放在一个表中,其余字段(我不需要如此快速访问)放在另一个表中。

这听起来像是外键的

用途,但似乎我的情况不一定需要外键的复杂性,因为我在坐标表和其他数据表之间有一个简单的 1 对 1 对应关系——坐标表的每一行对应于另一个数据表的相同行号, 所以这真的就像我在两个表中"拆分"每条记录一样。

所以问题是:我当然可以自己管理这种拆分,方法是为每个记录向两个表添加一行,并从两个表中删除一行以删除记录。但是有没有办法让 SQLite 为我管理这种拆分(我在谷歌上搜索了"sqlite 跨表拆分记录"但没有找到太多)?

  1. 索引通常用于搜索和排序。但是,如果查询中实际使用的所有列都是单个索引的一部分,则您有一个覆盖索引,并且可以在不访问实际表的情况下执行查询。

    coordinates列上的索引可能会加快此查询的速度。

  2. 即使具有 1:1 关系,您仍然需要知道哪些行是关联的,因此您仍然需要一个表中的外键。(这也恰好是主键,因此实际上您只在两个表中复制了主键列。

    如果您没有整数主键,则可以使用内部 ROWID 而不是主键。