优化所有记录的 SQLite 读取
optimize SQLite read of all records
问题摘要
我可以非常快速地从单列表的单列中读取所有值。如何从具有其他几列的表中的单列中快速读取所有值?
详
我正在使用 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 跨表拆分记录"但没有找到太多)?
-
索引通常用于搜索和排序。但是,如果查询中实际使用的所有列都是单个索引的一部分,则您有一个覆盖索引,并且可以在不访问实际表的情况下执行查询。
coordinates
列上的索引可能会加快此查询的速度。 -
即使具有 1:1 关系,您仍然需要知道哪些行是关联的,因此您仍然需要一个表中的外键。(这也恰好是主键,因此实际上您只在两个表中复制了主键列。
如果您没有整数主键,则可以使用内部 ROWID 而不是主键。
- 理解boost::asio-async_read在无需读取内容时的行为
- 使用新行和不使用新行读取文件
- 读取文件并输入到矢量中
- 查询SQLite数据库中的日期
- 用c++从输入文件中读取另一行
- 读取文件的最后一行并输入到链接列表时出错
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- 无法找到/读取配置文件.conf-FileIOException
- 带内存和隔离功能的SQLite
- 如何使用Luacneneneba API正确读取字符串和表参数
- C++将文本文件中的数据读取到结构数组中
- 正在将csv文件读取为双精度矢量
- 为什么 sscanf 无法从一个字符串中读取uint64_t和字符?
- 为什么在读取文件大小时文件IO速度会发生变化
- 正在读取二进制文件(is_open)
- 将sqlite原始数据读取到qbyTearray
- 如何从另一个平台(iOS到Windows)打开和读取SQLite数据库
- 优化所有记录的 SQLite 读取
- 如何使用C++读取sqlite数据
- 从blob SQLite读取二进制图像并使用OpenCV imdecode解码的最佳方法是什么?