SqLeI3C++对5个双字段选择查询的性能问题

SqLeI3C++对5个双字段选择查询的性能问题,c++,sql,database-design,sqlite,database-performance,C++,Sql,Database Design,Sqlite,Database Performance,我使用SQLite3来存储一个包含大约1000000个节点的5D规则网格,并且SELECT查询的性能存在一些问题 上下文 数据库描述 每个条目由5+25个双精度项组成,表示常规栅格节点上的一个点: 5第一双精度:5D规则栅格v1、v2、…、v5上点的坐标 25以下双精度:一些特性p1、p2、…、p25 每个点都是唯一的,前5个值的任何组合都是唯一的。 该表是使用创建表myTablev1 double、…、v5 double、p1 double、…、p25 double创建的。我没有添加具体的约束

我使用SQLite3来存储一个包含大约1000000个节点的5D规则网格,并且SELECT查询的性能存在一些问题

上下文 数据库描述 每个条目由5+25个双精度项组成,表示常规栅格节点上的一个点:

5第一双精度:5D规则栅格v1、v2、…、v5上点的坐标 25以下双精度:一些特性p1、p2、…、p25 每个点都是唯一的,前5个值的任何组合都是唯一的。 该表是使用创建表myTablev1 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|...
...
我已经在这个表上创建了一个索引,在我的表v1、v2、v3、v4、v5上使用createindex idx

选择查询描述 我想在5D网格中做一个三次插值。因此,我必须在每个维度中围绕我想要的点提取4个点。我的SELECT查询应返回4*4*4*4=1024点

由于符号属性,我必须进行16次查询,而不是1次。每个请求的形式为从myTable中选择*,其中v1=X和v2=X,v3在x1和x2之间,v4在y1和y2之间,v5在z1和z2之间。 事实上,v1和v2是角度。在我的5D网格中,我的值从-165到180,步长为15°。因此,如果我想在-160处插入一个值,我不能对-180和-135之间的v1类型进行查询,以得到-180,-165,-150,-135,因为我的表中不存在-180。我可以优化这一部分,只进行4次查询,但这不是我主要关心的问题

我用的是一个事先准备好的声明: sqlite3_prepare_v2db,从myTable中选择*其中v1=?和v2=?和v3之间?和和v4之间?和那他们之间呢?AND?,长度,语句,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\u open\u v2path,&db,SQLITE\u open\u READONLY,NULL

问题 进行16次查询和提取1024个分数大约需要2.5秒。Sqlite3操作占用99.8%的计算工作量

我做错了什么

我尝试过从myTable中解释查询计划SELECT*,其中v1=0和v2=0,v3介于0和3之间,v4介于0和3之间,v5介于0和3之间。
结果是使用索引idx v1=?搜索表myTable?和v2=?和v3>?当使用相等比较进行查找时,v3Normal索引工作得最好。 正如您在解释查询计划输出中所看到的,非相等比较会阻止使用索引的任何其他列;数据库必须扫描所有可能的v4和v5行以查找结果

在常规栅格中查询的点相当少,因此可以准确地知道所需所有点的坐标。 只需使用一个简单的查询,搜索具有所有五个精确坐标的点,并执行1024次。 这将导致更高效的单索引查找,即使它是针对每个点执行的

要使多个查询更加高效,请将所有查询打包到一个事务中

使用单独的索引查找点。 R-树针对多维区间查询进行了优化。 这将导致如下查询:

挑选* 从myTable 选择id中的rowid所在的位置 从RtreeIndexTable 其中v1=? 和v2=? 和v3之间?和 和v4之间?和 那他们之间呢?和 R-树通常用于不规则或稀疏数据;如果您可以查询单个点而不受影响,那么R-树可能会有过大的杀伤力


1.请给出表/约束/索引DDL。2.什么是循环属性?为什么说它们阻止使用单个查询?一些显然需要循环的东西的本质是什么?我更新并完成了我的问题。我更改了代码,从myTable中进行1024次SELECT*形式的查询,其中v1=?和v2=?和v3=?v4=?v5=?。我的性能提高了125倍,现在只需要大约20毫秒而不是2500毫秒就可以进行1024次查询并获取结果。。。我稍后会尝试R树,但现在你让我开心。谢谢你的帮助!我应该先尝试一下显而易见的请求,但我永远也猜不到这两种请求之间存在如此大的差异。。。这似乎很合乎逻辑!再次感谢:R-tree可能比这慢。是的,你可能是对的,但是Guttman在R-tree上发表的文章似乎很有趣,我会尝试一下。无论如何,对于我的应用程序来说,20毫秒的插值时间就足够了,如果在使用数据库之前将其复制到内存中,我的性能会得到大约40%的提高。