提问者:小点点

在Couchbase中调用删除文档(带分页)时,Spring数据“TimeoutException”


我们的Spring Boot应用程序使用的是一个CouchbaseDB,并使用

要从存储桶中删除记录,我们在存储库中创建了以下方法:

Slice<Dog> deleteAllByOwnerIdAndName(String ownerId, String name, Pageable pageable);

我们在桶上也有相关的索引:

CREATE INDEX `dogs_by_ownerId_and_name_idx` ON `dogs`(`ownerId`,`name`) WHERE (`_class` = "com.example.Dog")

我们的代码在尝试删除元素时使用分页:

 Slice<Dog> dogsSlice = null;
 Pageable pageable = PageRequest.of(0, 1000, Sort.by("id"));
 int pageCounter = 0;
 do {
   log.debug("Deleting page No. {} of dogs", pageCounter++);
   dogsSlice = dogsRepository.deleteAllByOwnerIdAndName("3243242", "Max", pageable);
 } while (dogsSlice.hasNext());

但是,很多时候我们得到超时例外:

删除狗的第0页

o.s.s.s.TaskUtils$日志记录错误处理程序:计划任务中发生意外错误。

由于以下 n1ql 错误,无法执行查询:{“消息”:“超时 7.5 秒超过”,“代码”:“超时超过 7.5 秒”,“代码”:1080} 在 org.springframework.data.couchbase.core.Couchbase.Couchbase.Cachbase.Cachbase.findByN1QL(沙发库模板.java:458) ~[类!/:5.1.40] 在组织.springframework.data.couchbase.存储库.query.AbstractN1ql基于查询执行切片(摘要N1qlBasedQuery.java:189) ~[类!/:5.1.40] 在组织.springframework.data.couchbase.repository.query.AbstractN1qlBasedQuery.executeDependingOnType(AbstractN1qlBasedQuery.java:129) ~[类!/:5.1.40] 在 org.springframework.data.couchbase.repository.query.AbstractN1qlBasedQuery.execute(AbstractN1qlBasedQuery.java:106) ~[类!/:5.1.40] 在组织.springframework.data.repository.core.support.repositoryFactory 支持$QueryExecud方法感知器.doInvoke(存储库工厂支持.java:590) ~[类!/:5.1.40] 在组织.springframework.data.存储库.core.support.存储库支持$查询探索者方法接收器.invoke(存储库工厂支持.java:578) ~[类!/:5.1.40] 在组织.springframework.aop.框架.反射方法调用.进行(反射方法调用.java:185) ~[类!/:5.1.40] 在组织.springframe.data.投影.默认方法对讲机.invoke(默认方法对流方法交互器.java:59) ~[类!/:5.50]在组织.springframework.aop.框架.反射方法调用.继续 (反射方法调用.java:185) ~[类!/:5.1.40] 在组织.springframework.data.couchbase.存储库.支持.视图后处理器$视图接收器调用(视图后处理器.java:87) ~[类!/:5.1.40] 在组织.Spring框架.aop.框架.反射方法调用.进行(反射方法调用.java:185) ~[类!/:5.1.40] 在调用(暴露调用感知器.java:92) ~[类!/:5.1.40] 在组织.springframework.aop.框架.反射方法调用.继续(反射方法调用.java:185) ~[类!/:5.1.40] 在组织.springframework.aop.拦截器.暴露调用接收器.invoke(暴露调用接收器.java:92) ~[类!/:5.1.40] 在组织Spring框架.aop.框架.反射方法调用.进行(反射性方法调用.java:185) ~[类!/:5.1.40] 在组织Spring框架.数据存储库.核心.支持.周围事务侦测器方法接收器.invoke(环境传态检测器方法交互器.java:61) ~[类!/:5.1.40] 在组织Spring框架.aop.框架.反射方法调用.进行(反射方法调用.java:185) ~[类!/:5.1.40] 在组织Spring框架工作.aopProxy.invoke(JdkDynamicAopProxy.java:212) ~[类!/:5.1.40] 在 com.sun.proxy.$Proxy 130.删除所有所有者 Id 和名称(未知来源) ~[na:na]

我们还需要做些什么吗?


共3个答案

匿名用户

你可以改进一些事情:

1)将索引更改为按所有者Id排序,然后在删除时,也按所有者Id排序

CREATE INDEX `dogs_by_ownerId_and_name_idx` ON `dogs`(`ownerId` ASC,`name`) WHERE (`_class` = "com.example.Dog") 

由于您的索引已经排序,couchbase不会在删除过程中花费额外的时间来排序它。

2) 你真的需要返回所有删除的对象吗?Couchbase必须在将文档发回给您之前将所有不在索引中的属性都带回来,此操作将需要一些额外的时间。最好的方法是只返回id。

@Override
public void updateFamilyName(String familyName, String familyId) {

    String queryString = "Delete from "+getBucketName()+" WHERE "+getClassFilter()+" " +
            " and familyId = '"+familyId+"' RETURNING meta().id";

    N1qlParams params = N1qlParams.build().consistency(ScanConsistency.REQUEST_PLUS).adhoc(true);
    ParameterizedN1qlQuery query = N1qlQuery.parameterized(queryString, JsonObject.create(), params);
    checklistRepository.getCouchbaseOperations().getCouchbaseBucket().query(query);
}

private String getBucketName(){
    return checklistRepository.getCouchbaseOperations().getCouchbaseBucket().bucketManager().info().name();
}

private String getClassFilter(){
    return "_class = '" + Checklist.class.getName() + "' ";
}

3)你也可以改进你的分页,但我认为在你的情况下没有必要。

https://blog.couchbase.com/offset-keyset-pagination-n1ql-query-couchbase/

匿名用户

如果查询具有 ORDER BY,如果可能,优化程序将尝试使用索引顺序。如果不可能,它必须生成所有可能的数据集并对数据进行排序以满足查询,即使分页需要很少的项目。

检查规则#7https://blog.couchbase.com/create-right-index-get-right-performance/

另请参阅此文章 https://blog.couchbase.com/offset-keyset-pagination-n1ql-query-couchbase/

匿名用户

排序。by(“id”)导致查询延迟,因为Couchbase似乎正在按该条件对整个文档集合进行排序。

因此,如果对结果进行排序没有真正的需要,则最好使用

分页分页=PageRequest.of(0,1000);