向超过百万条记录的现有文档添加字段
Add field to existing documents over million records
场景
我们在一个存储桶中有超过 500 万份文档,所有文档都嵌套了 JSON 一个简单的 uuid 键。我们想为所有文档添加一个额外字段。
例子
ee6ae656-6e07-4aa2-951e-ea788e24856a
{
"field1":"data1",
"field2":{
"nested_field1":"data2"
}
}
添加额外字段后
ee6ae656-6e07-4aa2-951e-ea788e24856a
{
"field1":"data1",
"field3":"data3",
"field2":{
"nested_field1":"data2"
}
}
它只有一个主索引:CREATE PRIMARY INDEX idx FOR bucket
。
问题
这需要很长时间。我们用 n1ql 试了一下,UPDATE bucket SET field3 = data3
。还有子文件突变。但所有这一切都需要几个小时。它是用 Go 编写的,所以我们可以将它放入一个 goroutine 中,但是时间还是太长了。
问题
有什么解决办法可以减少那个时间吗?
由于您需要添加新字段,而不是修改任何现有字段,因此最好使用 SDK SUBDOC API vs N1QL UPDATE(这是整个文档更新并需要获取文档)。
最好的选择是使用 N1QL 获取文档密钥然后使用
SDK SUBDOC API 添加你需要的字段。您可以使用反应式 API(异步)
您有 500 万个文档,主索引使用如下
val = ""
In loop
SELECT RAW META().id FROM mybucket WHERE META().id > $val LIMIT 10000;
SDK SUBDOC update
val = last value from the SELECT
https://blog.couchbase.com/offset-keyset-pagination-n1ql-query-couchbase/
Eventing Service 可以非常高效地执行这些类型的丰富任务。即使是低端系统也应该能够在两 (2) 分钟内完成 500 万行。
// Note src_bkt is an alias to the source bucket for your handler
// in read+write mode supported for version 6.5.1+, this uses DCP
// and can be 100X more performant than N1QL.
function OnUpdate(doc, meta) {
// optional filter to be more selective
// if (!doc.type && doc.type !== "mytype") return;
// test if we already have the field we want to add
if (doc.field3) return;
doc.field3 = "data3";
src_bkt[meta.id] = doc;
}
有关 Eventing 的更多详细信息,请参阅 https://docs.couchbase.com/server/current/eventing/eventing-overview.html 我通常会丰富 10 亿个文档中的 3/4。如果您将 Eventing 函数设置中的工作人员数量从 3 增加到 16,Eventing 函数也会 运行 更快(每秒丰富更多文档),前提是您的 Eventing 节点上有 8 个以上的物理核心。
我测试了上述 Eventing 函数,它在我的非 MDS 单节点 couchbase 测试系统(12 核,2.2GHz)上仅用了 72 秒就丰富了 5M 文档(以您的示例为模型)。显然,如果你有一个真正的多节点集群,它会更快(也许所有 5M 文档仅需 5 秒)。
场景
我们在一个存储桶中有超过 500 万份文档,所有文档都嵌套了 JSON 一个简单的 uuid 键。我们想为所有文档添加一个额外字段。
例子
ee6ae656-6e07-4aa2-951e-ea788e24856a
{
"field1":"data1",
"field2":{
"nested_field1":"data2"
}
}
添加额外字段后
ee6ae656-6e07-4aa2-951e-ea788e24856a
{
"field1":"data1",
"field3":"data3",
"field2":{
"nested_field1":"data2"
}
}
它只有一个主索引:CREATE PRIMARY INDEX idx FOR bucket
。
问题
这需要很长时间。我们用 n1ql 试了一下,UPDATE bucket SET field3 = data3
。还有子文件突变。但所有这一切都需要几个小时。它是用 Go 编写的,所以我们可以将它放入一个 goroutine 中,但是时间还是太长了。
问题
有什么解决办法可以减少那个时间吗?
由于您需要添加新字段,而不是修改任何现有字段,因此最好使用 SDK SUBDOC API vs N1QL UPDATE(这是整个文档更新并需要获取文档)。
最好的选择是使用 N1QL 获取文档密钥然后使用 SDK SUBDOC API 添加你需要的字段。您可以使用反应式 API(异步)
您有 500 万个文档,主索引使用如下
val = ""
In loop
SELECT RAW META().id FROM mybucket WHERE META().id > $val LIMIT 10000;
SDK SUBDOC update
val = last value from the SELECT
https://blog.couchbase.com/offset-keyset-pagination-n1ql-query-couchbase/
Eventing Service 可以非常高效地执行这些类型的丰富任务。即使是低端系统也应该能够在两 (2) 分钟内完成 500 万行。
// Note src_bkt is an alias to the source bucket for your handler
// in read+write mode supported for version 6.5.1+, this uses DCP
// and can be 100X more performant than N1QL.
function OnUpdate(doc, meta) {
// optional filter to be more selective
// if (!doc.type && doc.type !== "mytype") return;
// test if we already have the field we want to add
if (doc.field3) return;
doc.field3 = "data3";
src_bkt[meta.id] = doc;
}
有关 Eventing 的更多详细信息,请参阅 https://docs.couchbase.com/server/current/eventing/eventing-overview.html 我通常会丰富 10 亿个文档中的 3/4。如果您将 Eventing 函数设置中的工作人员数量从 3 增加到 16,Eventing 函数也会 运行 更快(每秒丰富更多文档),前提是您的 Eventing 节点上有 8 个以上的物理核心。
我测试了上述 Eventing 函数,它在我的非 MDS 单节点 couchbase 测试系统(12 核,2.2GHz)上仅用了 72 秒就丰富了 5M 文档(以您的示例为模型)。显然,如果你有一个真正的多节点集群,它会更快(也许所有 5M 文档仅需 5 秒)。