SQLite3 c++对5个双字段的SELECT查询的性能问题
SQLite3 c++ perfomance issues with SELECT query on 5 double fields
我使用SQLite3来存储约1 000 000个节点的5D规则网格,并且在"SELECT"查询的性能方面存在一些问题。
<<h2>上下文/h2>数据库描述每个条目由5+25个double组成,代表规则网格(节点)上的一个点:
- 5第一个double:点在5D规则网格上的坐标(v1,v2,…,v5)
- 25以下双精度:一些特性(p1,p2,…,p25)
每个点都是唯一的(前5个值的任何组合都是唯一的)。该表是用CREATE TABLE myTable(v1 double,..., v5 double, p1 double,..., p25 double)
创建的。我没有添加特别的约束。
条目在它们的坐标之后按升序排序(v1,然后v2,然后v3,…):
v1|v2|v3|v4|v5|p1|p2|p3|...
0| 0| 0| 0| 0| x| x| x|...
0| 0| 0| 0| 1| x| x| x|...
0| 0| 0| 0| 2| x| x| x|...
...
0| 0| 0| 1| 0| x| x| x|...
0| 0| 0| 1| 1| x| x| x|...
0| 0| 0| 1| 2| x| x| x|...
...
我已经在这个表上创建了一个INDEX,使用CREATE INDEX idx ON myTable (v1,v2,v3,v4,v5)
SELECT查询描述
我想在5D网格中做一个"立方"插值。所以我需要在每个维度上,在我想要的点周围抽取4个点。我的SELECT查询应该返回4*4*4*4=1024点。
由于对称属性,我必须进行16次查询而不是1次。每个请求的格式为SELECT * FROM myTable WHERE (v1=X AND v2=X AND v3 BETWEEN x1 AND x2 AND v4 BETWEEN y1 AND y2 AND v5 BETWEEN z1 AND z2)
。的确,v1和v2是角。在我的5D网格中,我的值从-165到180,步长为15°。因此,如果我想在-160插入一个值,我不能对v1 BETWEEN -180 AND -135
类型进行查询(以获得-180,-165,-150,-135),因为-180在我的表中不存在。我可以优化这部分,只做4个查询,但这不是我主要关心的。
我使用一个准备好的语句:
sqlite3_prepare_v2(db,"SELECT * FROM myTable WHERE (v1=? AND v2=? AND v3 BETWEEN ? AND ? AND v4 BETWEEN ? AND ? AND v5 BETWEEN ? AND ?"),length,statement,NULL)
然后,对于每个查询,我做:
sqlite3_bind_double(statement, int, double);
while(sqlite3_step(statement)==SQLITE_ROW) {
// for each row (for each "node") :
// 1) retrieve its properties
double myvar1 = sqlite3_colum_double(statement,6)
double myvar2 = sqlite3_colum_double(statement,7)
....
double myvar25 = sqlite3_colum_double(statement,25)
// 2) create the object and add it to a vector for the interpolation
}
sqlite3_reset(statement);
sqlite3_clear_bindings(statement);
数据库以sqlite3_open_v2(path,&db,SQLITE_OPEN_READONLY,NULL)
执行16次查询并提取1024个点大约需要2.5秒。Sqlite3操作占用99.8%的计算量(callgrind)…
我做错了什么?
我试过EXPLAIN QUERY PLAN SELECT * FROM myTable WHERE (v1=0 AND v2=0 AND v3 BETWEEN 0 AND 3 AND v4 BETWEEN 0 AND 3 AND v5 BETWEEN 0 AND 3
。结果是SEARCH TABLE myTable USING INDEX idx (v1=? AND v2=? AND v3>? AND v3<?)
基于5个坐标创建唯一索引并进行1024次查询会更快吗?在此之前,我使用vector和通过索引直接访问
普通索引在使用相等比较(=
)进行查找时效果最好。正如您在EXPLAIN QUERY PLAN输出中看到的,非相等比较会阻止使用索引的任何其他列;数据库必须扫描所有可能的v4
和v5
行来查找结果。
-
您在规则网格中查询相当少的点,因此您确切地知道您想要的所有点的坐标。只需使用一个简单的查询,用所有五个精确坐标搜索一个点,并执行1024次。这将导致更高效的单个索引查找,即使它是针对每个点执行的。
要使多个查询更高效,请将所有查询封装在单个事务中。 使用单独的R-tree索引查找点。r树针对(多维)间隔查询进行了优化。这将导致如下查询:
SELECT * FROM myTable WHERE rowid IN (SELECT id FROM RtreeIndexTable WHERE v1 = ? AND v2 = ? AND v3 BETWEEN ? AND ? AND v4 BETWEEN ? AND ? AND v5 BETWEEN ? AND ?)
r树通常用于不规则或稀疏数据;
如果您可以查询单个点,那么r树可能是多余的。
- Mongodb c++驱动程序:如何查询元素的数组
- 查询SQLite数据库中的日期
- 如何在ArangoDb AQL查询中指定数据库
- Qt SQLite没有查询或参数计数不匹配
- 如何使用c++在VS 2019上运行SQL查询
- 从返回的顶点缓冲区查询顶点结构
- 以非特权用户身份查询 NTFS 特殊文件的元数据?
- C/C++ - 查询平台相关的换行符(用于内存映射文件)
- SQLite3 在 c++ 中输出 SELECT 上的空列表
- 查询 NFS 上的提升进程间::file_lock
- Qt JSON – 从子项查询
- 在 c++ 中解决段树以外的范围查询的有效方法是什么?
- 无法从 Win10 中的 IDirectDraw7 查询 IDirect3D7
- 如何在 sys/select.h 中正确使用
- CQL SELECT 查询在连接到暂存 Cassandra 服务器时挂起
- MySQL C++连接器使用SELECT查询获取字符串
- QSqlQuery禁止非SELECT查询
- select查询在编辑中总是返回-1
- SQLite3 c++对5个双字段的SELECT查询的性能问题
- 用c++在SQL Server上运行select查询最快的方式是什么?