4th*_*eam 5 java couchbase spring-data spring-data-couchbase couchbase-java-api
我对 couchbase 查询计划的工作方式理解有问题。我将 SpringData 与 Couchbase 4.1 结合使用,并提供 Couchbase 存储库的自定义实现。在我的 Couchbase 存储库的自定义实现中,我有以下方法:
String queryAsString = "SELECT MyDatabase.*, META().id as _ID, META().cas as _CAS FROM MyDatabase WHERE segmentId = $id AND _class = $class ORDER BY executionTime DESC LIMIT 1";
JsonObject params = JsonObject.create()
.put(CLASS_VARIABLE, MyClass.class.getCanonicalName())
.put(ID_VARIABLE, segmentId);
N1qlQuery query = N1qlQuery.parameterized(queryAsString, params);
List<MyClass> resultList = couchbaseTemplate.findByN1QL(query, SegmentMembers.class);
return resultList.isEmpty() ? null : resultList.get(0);
Run Code Online (Sandbox Code Playgroud)
结果,Spring Data 生成以下 json 对象,表示对 Couchbase 的查询:
{
"$class":"path/MyClass",
"statement":"SELECT MyDatabase.*, META().id as _ID, META().cas as _CAS from MyDatabase where segmentId = $id AND _class = $class ORDER BY executionTime DESC LIMIT 1",
"id":"6592c16a-c8ae-4a74-bc17-7e18bf73b3f8"
}
Run Code Online (Sandbox Code Playgroud)
当我通过 Java 和 N1QL Rest Api 或通过 cbq consol 执行它时,问题在于性能。为了在 cbq 中执行此查询,我只需将参数引用替换为精确值。
在 select 语句之前添加 EXPLAIN 子句后,我提到了不同的执行计划。通过 Java Spring Data 或 N1QL Rest Api 将此查询作为参数化查询执行 我已经提到过该查询不使用我为这种情况创建的索引。索引定义如下:
CREATE INDEX `testMembers` ON MyDatabase `m`(`_class`,`segmentId`,`executionTime`) WHERE (`_class` = "path/MyClass") USING GSI;
Run Code Online (Sandbox Code Playgroud)
因此,当我通过 cbq consol 执行查询时,Couchbase 使用我的 idnex 并且查询性能非常好。但是,当我通过 N1QL Rest api 或 Java 执行此查询时,我发现该查询不使用我的索引。您可以在下面找到证明这一事实的执行计划的一部分:
"~children": [
{
"#operator": "PrimaryScan",
"index": "#primary",
"keyspace": "CSM",
"namespace": "default",
"using": "gsi"
},
Run Code Online (Sandbox Code Playgroud)
那么,问题是 couchbase 查询优化器的行为正确且合法吗?这是否意味着查询计划不考虑参数的实际值?我是否手动将值放入查询字符串中,或者存在其他方式来使用 N1Ql 参数化查询和正确的索引选择?
编辑
根据shashi raj回答,我将 N1qlParams.build().adhoc(false) 参数添加到参数化 N1QL 查询中。这并不能解决我的问题,因为这个查询仍然存在性能问题。此外,当我打印查询时,我发现它与我之前描述的相同。所以,我的查询仍然分析错误并导致性能下降。
您的情况的问题是由于您有一个带有 'where' 子句的索引WHERE ( _class = "path/MyClass"),同时您_class在查询中将其作为参数传递。
因此,分析参数化查询的查询优化器不知道该查询可能使用为 创建的索引_class = "path/MyClass",因为它_class = $class位于 select 的 where 中。很简单,对吧?
因此,不要将索引的“where”中提到的任何字段作为选择参数传递。相反,_class = "path/MyClass"以与create index. 一切都应该很好。
这是 couchbase 问题跟踪系统中关于此问题的票证。
| 归档时间: |
|
| 查看次数: |
898 次 |
| 最近记录: |