DocumentDB - 量化存储过程中的有界执行

时间:2017-02-18 19:43:23

标签: javascript performance stored-procedures azure-cosmosdb

我有一个插入或更新的DocumentDB存储过程(不替换,而是读取和更新现有文档)。存储过程最多执行两个操作:

  1. 按ID和
  2. 查询
  3. 插入或更新
  4. 该文件也不是特别大。但是,我会不时地(由有界执行引起)或449(冲突更新资源,这是一个瞬态错误)。

    IMO这不是一个特别重要的存储过程,但似乎我已经遇到了限制。我可以在客户端做更多工作,但我喜欢存储过程中的ACID保证。

    有限执行是否有任何量化指标?我想知道我是在做错事还是确实达到了DocumentDB的限制。

    我的存储过程是修改后的https://github.com/Azure/azure-documentdb-js-server/blob/master/samples/stored-procedures/update.js,它接收文档而不是id。我特别使用“$ addToSet”,代码看起来像

    function unique(arr) {
        var uniqueArr = [], map = {};
    
        for (var i = 0; i < arr.length; i++) {
            var exists = map[arr[i]];
    
            if (!exists) {
                uniqueArr.push(arr[i]);
                map[arr[i]] = true;
            }
        }
    
        return uniqueArr;
    }
    
    // The $addToSet operator adds elements to an array only if they do not already exist in the set.
    function addToSet(document, update) {
        var fields, i;
    
        if (update.$addToSet) {
            console.log(">addToSet");
            fields = Object.keys(update.$addToSet);
    
            for (i = 0; i < fields.length; i++) {
                if (!Array.isArray(document[fields[i]])) {
                    // Validate the document field; throw an exception if it is not an array.
                    throw new Error("Bad $addToSet parameter - field in document must be an array.");
                }
    
                // convert to array if input is not an array
                var newIds = Array.isArray(update.$addToSet[fields[i]])
                    ? update.$addToSet[fields[i]]
                    : [update.$addToSet[fields[i]]];
    
                var finalIds = unique(document[fields[i]].concat(newIds));
                document[fields[i]] = finalIds;
            }
        }
    }
    

1 个答案:

答案 0 :(得分:2)

DocumentDB存储过程必须在5秒内完成。它们也受到集合的预配置吞吐量的限制。如果您配置了5000 RU / s,则存储过程总共不会消耗超过5000 * 5 RU。

当存储过程达到其执行时间或其吞吐量限制时,执行数据库操作(读取,写入,查询)的任何请求都将收到抢占信号,即该请求将不会被接受为该信号。存储过程包装执行,并返回给调用者。如果您检查每次调用的返回代码,您的存储过程将永远不会超时。这是一个显示如何执行此操作的代码段(https://github.com/Azure/azure-documentdb-js-server/blob/master/samples/stored-procedures/处提供完整示例):

var isAccepted = collection.replaceDocument(...) {
     // additional logic in callback
});

if (!isAccepted) {
   // wrap up execution and return        
}

关于449,这是一个并发错误,如果存储过程尝试执行冲突写入,则可以返回该错误。这是免费的副作用,可以安全地从客户端重试。每当遇到此错误时,您都可以实施重试,直到成功模式。