Couchbase 使用 Keyset 分页对记录进行排序 - 丢失记录

标签 couchbase sql++ keyset-pagination

我们在生产环境中运行 couchbase DB,存储桶中约有 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并传递给上面的查询。

但是我们发现在获取下一组记录时缺少一些记录。

我们在 couchbase 数据库中的索引

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

enter image description here

最佳答案

索引类似于 b 树,即在第一个键、第二个键...中进行排序。

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

以下方法很复杂。验证结果正确性,谨慎使用。

使用内部查询,只做第一个不相等并使用索引顺序。这样,您就可以在靠近停止位置而不是从头开始扫描的位置开始扫描。

外部查询应用其他谓词消除进一步已经看到的。一旦达到 LIMIT 将停止,而不是继续产生所有值。

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“”

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

关于Couchbase 使用 Keyset 分页对记录进行排序 - 丢失记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76163709/

相关文章:

Couchbase N1q1 更新数组元素并仅返回更新后的 block

sql-server - SQL Server 中两个表的分页

docker - 在Windows 10的Docker中运行具有多个节点的Couchbase群集

caching - 提供缓存即服务是个好主意吗?

java - CouchbaseClient VS CouchbaseCluster

couchbase - 存储桶内更改的异步客户端通知

Couchbase N1QL 连接查询 - 语法错误

couchbase - 限制数组大小 Couchbase 更新查询