【发布时间】:2015-02-27 16:13:50
【问题描述】:
您好,我正在使用 16 个集合来插入大约 3-4 百万个 json 对象,每个对象从 5-10k 不等。我使用存储过程来插入这些文档。我有 22 个容量单元。
function bulkImport(docs) {
var collection = getContext().getCollection();
var collectionLink = collection.getSelfLink();
// The count of imported docs, also used as current doc index.
var count = 0;
// Validate input.
if (!docs) throw new Error("The array is undefined or null.");
var docsLength = docs.length;
if (docsLength == 0) {
getContext().getResponse().setBody(0);
}
// Call the CRUD API to create a document.
tryCreateOrUpdate(docs[count], callback);
// Note that there are 2 exit conditions:
// 1) The createDocument request was not accepted.
// In this case the callback will not be called, we just call setBody and we are done.
// 2) The callback was called docs.length times.
// In this case all documents were created and we don't need to call tryCreate anymore. Just call setBody and we are done.
function tryCreateOrUpdate(doc, callback) {
var isAccepted = true;
var isFound = collection.queryDocuments(collectionLink, 'SELECT * FROM root r WHERE r.id = "' + doc.id + '"', function (err, feed, options) {
if (err) throw err;
if (!feed || !feed.length) {
isAccepted = collection.createDocument(collectionLink, doc, callback);
}
else {
// The metadata document.
var existingDoc = feed[0];
isAccepted = collection.replaceDocument(existingDoc._self, doc, callback);
}
});
// If the request was accepted, callback will be called.
// Otherwise report current count back to the client,
// which will call the script again with remaining set of docs.
// This condition will happen when this stored procedure has been running too long
// and is about to get cancelled by the server. This will allow the calling client
// to resume this batch from the point we got to before isAccepted was set to false
if (!isFound && !isAccepted) getContext().getResponse().setBody(count);
}
// This is called when collection.createDocument is done and the document has been persisted.
function callback(err, doc, options) {
if (err) throw err;
// One more document has been inserted, increment the count.
count++;
if (count >= docsLength) {
// If we have created all documents, we are done. Just set the response.
getContext().getResponse().setBody(count);
} else {
// Create next document.
tryCreateOrUpdate(docs[count], callback);
}
}
我的 C# 代码如下所示
public async Task<int> Add(List<JobDTO> entities)
{
int currentCount = 0;
int documentCount = entities.Count;
while(currentCount < documentCount)
{
string argsJson = JsonConvert.SerializeObject(entities.Skip(currentCount).ToArray());
var args = new dynamic[] { JsonConvert.DeserializeObject<dynamic[]>(argsJson) };
// 6. execute the batch.
StoredProcedureResponse<int> scriptResult = await DocumentDBRepository.Client.ExecuteStoredProcedureAsync<int>(sproc.SelfLink, args);
// 7. Prepare for next batch.
int currentlyInserted = scriptResult.Response;
currentCount += currentlyInserted;
}
return currentCount;
}
我面临的问题是我尝试插入的 400k 个文档中,有时会丢失文档而没有给出任何错误。
应用程序是部署在云端的工作者角色。 如果我增加在 documentDB 中插入的线程或实例的数量,那么丢失的文档数量会高得多。
如何找出问题所在。在此先感谢。
【问题讨论】:
-
this question(讨论您可能遇到的异常)或this question(提供您可能已经看过的代码示例)有什么有用的吗?
-
是的,我已经看到了..由于某些未知原因,文档数据库在批量插入时跳过添加文档...我在这里谈论的是百万个文档,它有点零星
-
能否请您给我发电子邮件,以便我们进一步深入研究。我们需要您提供一些详细信息,例如端点名称、活动 ID 等。
-
是的,我仍然在寻找不同的方面会回来看起来我们正在解决它...将发布我为解决问题所做的不同更改...跨度>
-
这里是对我的代码所做的更改 1) 我现在使用 Wait() 来确保任务完成,而不是使用任务触发存储过程。 2) 我现在不仅捕获聚合异常,还捕获异常 3) 在具有 2 个实例和 16 个并发调用消息选项的 D2 机器中进行调整 4) 使用 Document DB Standard S1,收集与容量单位比率为 1:1 ....谢谢所有的帮助
标签: azure bulkinsert azure-cosmosdb