Couchbase 使用 Keyset 分页对记录进行排序 - 缺少记录

问题描述 投票:0回答:1

我们在生产环境中运行了 couchbase 数据库,一个桶中包含约 4,300,000 个文档

我们正在尝试以分页方式检索记录。目前我们正在使用基于偏移量的分页 例如。为了检索我们使用以下查询的前 20 条记录,我们正在增加偏移值以获取后续记录。

SELECT   startdatetime,
         id,
         Meta().id as m_id
FROM     test_document USE index (test_doc_with_order using gsi)
WHERE    customerId='343434375317c0523ce020d6'
AND      accountId='12233322'
AND      documentType='TESTING'
AND      documentStatus IN ["ACTIVE", "NEW", "OLD"]
ORDER BY startDateTime,
         meta().id limit 20 offset 0

但是当我们遍历偏移量(意味着获取下一组记录)时,这种方法会线性增加我们的查询执行时间。所以我们决定参考 blog

移动这个基于键集的分页查询

在获取第一页后,我们使用下面的查询来获取下一组记录

SELECT   startdatetime,
         id,
         Meta().id as m_id
FROM     test_document USE index (test_doc_with_order using gsi)
WHERE    customerId='343434375317c0523ce020d6'
AND      accountId='12233322'
AND      documentType='TESTING'
AND      documentStatus IN ["ACTIVE", "NEW", "OLD"]
AND      startDateTime >= 'last_document_startTime-2023-04-16T20:12:00Z'
AND      meta().id > "last_document_meta_id"
ORDER BY startDateTime,
         meta().id limit 20

获取最后一个文档 meta().id 和 startDateTime 并传递给上面的查询。

但是我们发现在获取下一组记录时丢失了一些记录。

沙发底座数据库中的索引

CREATE INDEX `test_doc_with_order` ON `test_document`(`documentType`,`customerId`,`accountId`,`testDocumentId`,`documentStatus`,`startDateTime`, `Meta().id`) WHERE (`documentType` = "TESTING")}

couchbase n1ql keyset-pagination
1个回答
2
投票

Index 在类似 b-tree 上使用,即在第一个键中,第二个键,...被排序。

键集分页仅在所有谓词都具有单一相等性且唯一键具有范围时才有效。

下面的方法比较复杂。验证结果正确性,谨慎使用

使用内部查询,只做第一个不相等并使用索引顺序。这样你就可以从你离开的地方开始扫描,而不是从开始的地方开始扫描。

外部查询应用其他谓词消除进一步已经看到。 LIMIT 将在达到 vs 继续产生所有值后停止。

CREATE INDEX ix100 ON default(customerId,accountId,startDateTime, meta().id)
           WHERE documentType = "TESTING" AND documentStatus IN ["ACTIVE", "NEW", "OLD"];

SELECT d. startDateTime, d.m_id
FROM ( SELECT   startDateTime, META().id AS m_id
       FROM     default USE INDEX (ix100)
       WHERE    customerId = '343434375317c0523ce020d6'
                AND accountId = '12233322'
                AND documentType = 'TESTING'
                AND documentStatus IN ["ACTIVE", "NEW", "OLD"]
                AND startDateTime >= $last_startdate
       ORDER BY startDateTime, META().id
      ) AS d
WHERE d.startDateTime != $last_startdate OR d.m_id > $last_docid
LIMIT 20;

从 $last_startdate 开始你的开始日期 $last_docid“”

Next 循环更改为最后一行值并重复直到没有更多结果

© www.soinside.com 2019 - 2024. All rights reserved.