2

Ich habe eine DocumentDB-gespeicherte Prozedur, die Einfügen oder Aktualisieren (nicht ersetzen, sondern liest und aktualisiert vorhandenes Dokument). Die gespeicherte Prozedur tut höchstens zwei Operationen:DocumentDB - Begrenzte Ausführung in gespeicherter Prozedur quantifizieren

  1. Abfrage von Id und
  2. entweder einfügen oder aktualisieren

Das Dokument ist auch nicht besonders groß. Hin und wieder würde ich jedoch entweder eine Zeitüberschreitung (verursacht durch beschränkte Ausführung) oder 449 (Konfliktaktualisierungsressourcen, was ein vorübergehender Fehler ist) erhalten.

IMO Dies ist keine besonders anstrengende gespeicherte Prozedur, aber scheint, dass ich zu Einschränkungen bereits laufen werde. Ich könnte mehr Arbeit Clientseite tun, aber ich liebe die ACID-Garantie in der gespeicherten Prozedur.

Gibt es ein quantitatives Maß für die beschränkte Ausführung? Ich frage mich, ob ich einfach etwas falsch mache oder tatsächlich Limit von DocumentDB erreicht habe.

Meine gespeicherte Prozedur ist eine modifizierte https://github.com/Azure/azure-documentdb-js-server/blob/master/samples/stored-procedures/update.js, die Dokument anstelle von ID einnimmt. Ich bin mit „$ addToSet“ im Besonderen und der Code sieht aus wie

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; 
     } 
    } 
} 

Antwort

1

DocumentDB gespeicherten Prozeduren innerhalb von 5 Sekunden durchführen müssen. Sie sind auch durch den bereitgestellten Durchsatz der Sammlung begrenzt. Wenn Sie 5000 RU/s bereitgestellt haben, kann die gespeicherte Prozedur insgesamt nicht mehr als 5000 * 5 RUs verbrauchen.

Wenn eine Stored Procedure ihre Ausführungszeit oder ihren Durchsatzlimit erreicht, wird jede Anforderung zur Durchführung einer Datenbankoperation (Lesen, Schreiben, Abfragen) ein Vorbelegungssignal erhalten, dh die Anforderung wird nicht als Signal für akzeptiert die gespeicherte Prozedur, um die Ausführung abzuschließen und zum Aufrufer zurückzukehren. Wenn Sie bei jedem Aufruf nach dem Rückkehrcode suchen, wird die gespeicherte Prozedur niemals ablaufen. Hier ist ein Ausschnitt zeigt, wie dies zu tun (Voll Proben zur Verfügung stehen 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   
} 

In Bezug auf 449, ist dies ein Concurrency Fehler, die zurückgegeben werden können, wenn Ihre gespeicherte Prozedur eine widersprüchliche Schreib auszuführen versucht. Dies ist nebenwirkungsfrei und kann vom Client erneut versucht werden. Sie können einen Wiederholungsversuch implementieren, bis das Muster erfolgreich ist, wenn Sie auf diesen Fehler stoßen.

+0

Sollten sie diese begrenzten Ausführungsgrenzen mit nur zwei Operationen erreichen? Ich weiß, dass es RUs verbraucht, aber könnte es sein, dass alle RUs von anderen Operationen verbraucht werden, wenn dieser ausgeführt wird? –

+0

@Aravind danke für die zusätzlichen Informationen, aber etwas summiert sich nicht. Einige zusätzliche Hintergrundinformationen 1) Die Umgebung ist unsere Entwicklungsumgebung und dies ist eine Funktion, die noch nicht aktiviert ist, so erwarte ich praktisch keinen Verkehr neben Entwicklern. 2) Die Sammlung ist eine partitionierte Sammlung mit 2500 RU. Schließlich habe ich festgestellt, dass das Timeout von der Auswahl ist, die nach ID und Partitionsschlüssel fragt. Das ist ziemlich unerwartet –

+0

Nur um zu bemerken, dass wir seither auf 2 REST-Aufrufe auf dem Client zurückgekehrt sind. # 1 Abfrage nach ID + Partition Schlüssel # 2 Upsert Für # 2 verlassen wir uns auf optimistische Nebenläufigkeit, da wir nicht erwarten, dass viele Kollisionen (es ist ein Batch-Prozess). Ich bin froh zu sagen, dass es sehr zuverlässig und viel schneller zu sein scheint, als beide Operationen im Stored Proc auszuführen. Trotzdem neugierig, warum ich so früh am Limit bin. –

Verwandte Themen