代码之家  ›  专栏  ›  技术社区  ›  riorio

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

  •  1
  • riorio  · 技术社区  · 7 年前

    我们的 Spring Boot 应用程序正在使用 Couchbase 数据库并使用 Spring-Data

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

    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());
    

    但是,太多次我们得到 Timeoutexceptioin :

    删除狗的第0页

    o.s.s.taskutils$loggingErrorHandler:计划任务中发生意外错误。

    org.springframework.data.couchbase.core.couchbasequeryexecutionexception:由于以下n1ql错误,无法执行查询: “msg”:“超过超时7.5s”,“code”:1080_ 在Org.Spring Frask.Dea.CoucBase.Cork.CouChaseBeMeldPo.FiffByNy1QL(CoukBaseTeMelpor.java:458)~(类)!::5.1.40] 在Org.Spring Frask.Dea.CoucBase.Reavory.Quest.ActudiaN1QLBaseQueQuest.ExistUsEclipse(抽象N1QLaseDeQuest.java:189)~[类]!::5.1.40] 在Org.Spring Frask.Dea.CoucBase.Reavory.Quest.ActudiaN1QLBaseQueQuest.ExcExtRealEngOnOnType(抽象N1QLaseDeqQual.java:129)~(类)!::5.1.40] 在Org.Spring Frask.Dea.CoucBase.Reavory.Quest.ActudiaN1qLaseDeqQue.Ex执行(ActudiaN1qLaseDeQuest.java:106)~[类]!/:5.1.40条] 在org .prgFrrask.Reavory.RealStory.Cork.SudioTororyForthyType支持$QueRealEuthororMeorTrasor.doNoCKE(ReavigoryForthyBuff.Java:590)~~类!::5.1.40] 在org .prgFrrask.Reavory.RealStory.Cork.SudioTororyFaseType支持$QueRealExtuorOrth.Trackort.JooKE(ReavigoryForthyBuff.Java:578)~~类!/:5.1.40条] 在Org.Spring Frask.AOP.FraseVoMeDoDoCorcOut.继续(反射式调用,Java:185)~(类)!::5.1.40] 在Org.Spring Frask.Debug .Debug方法BootoKing方法拦截器.Debug(Debug方法NoopoCKing方法拦截器.java:59)~(类)!::5.1.40] 在Org.Spring Frask.AOP.FraseVoMeDoDoCorcOut.继续(反射式调用,Java:185)~(类)!::5.1.40] 在Org.Spring Frask.Dea.CoucBase.Reavory.Sudio.VIEW处理器$VisualBaseTork.VooKE(VIEWPSPECTPROP.JAVA:87)~[类]!/:5.1.40条] 在Org.Spring Frask.AOP.FraseVoMeDoDoCorcOut.继续(反射式调用,Java:185)~(类)!::5.1.40] 在Org.Spring Frask.AOP。截取器。::5.1.40] 在Org.Spring Frask.AOP.FraseVoMeDoDoCorcOut.继续(反射式调用,Java:185)~(类)!/:5.1.40条] 在Org.Spring Frask.AOP。截取器。/:5.1.40条] 在Org.Spring Frask.AOP.FraseVoMeDoDoCorcOut.继续(反射式调用,Java:185)~(类)!::5.1.40] 在Org.Spring Frask.Reavory.RealStory.Cork.SudioTurnTraceTraceDeCortoRead拦截器.调用(SouthOnTunTraceCortoRead拦截器. Java:61)~(类)!::5.1.40] 在Org.Spring Frask.AOP.FraseVoMeDoDoCorcOut.继续(反射式调用,Java:185)~(类)!/:5.1.40条] 在Org.Spring Frask.AOP.Frask.jdkDyjiApPosix.JooKE(JDKDyjiApPotoServ.java:212)~(类)!::5.1.40] 在com.sun.proxy.$proxy130.deleteAllByOwnerIDandName(未知源)~[na:na]

    我们还需要做什么吗?

    3 回复  |  直到 7 年前
        1
  •  1
  •   deniswsrosa    7 年前

    您可以改进以下几点:

    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/

        2
  •  1
  •   vsr    7 年前

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

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

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

        3
  •  1
  •   riorio    7 年前

    这个 Sort.by("id") 导致查询延迟,因为CouchBase似乎正在根据该条件对整个文档集合进行排序。

    因此,如果不需要对结果进行排序,最好使用

    Pageable pageable = PageRequest.of(0, 1000);