Gewusst wie: Verwenden des Schritts „Ausführungsprofil“ zum Auswerten Ihrer Gremlin-Abfragen
GILT FÜR: Gremlin
Dieser Artikel enthält eine Übersicht über die Verwendung des Schritts „Ausführungsprofil“ für Azure Cosmos DB for Gremlin-Graphdatenbanken. In diesem Schritt werden relevante Informationen zur Problembehandlung und zu Abfrageoptimierungen bereitgestellt. Er ist mit allen Gremlin-Abfragen kompatibel, die für ein Cosmos DB-Gremlin-API-Konto ausgeführt werden können.
Fügen Sie zum Verwenden dieses Schritts einfach den Funktionsaufruf executionProfile()
am Ende Ihrer Gremlin-Abfrage an. Ihre Gremlin-Abfrage wird ausgeführt, und als Ergebnis des Vorgangs wird ein JSON-Antwortobjekt mit dem Ausführungsprofil der Abfrage zurückgegeben.
Beispiel:
// Basic traversal
g.V('mary').out()
// Basic traversal with execution profile call
g.V('mary').out().executionProfile()
Nach dem Aufrufen des Schritts executionProfile()
ergibt sich als Antwort ein JSON-Objekt, das den ausgeführten Gremlin-Schritt, die benötigte Gesamtdauer und ein Array mit den Cosmos DB-Runtimeoperatoren, zu denen die Anweisung geführt hat, enthält.
Hinweis
Diese Implementierung für „Ausführungsprofil“ ist nicht in der Apache Tinkerpop-Spezifikation definiert. Der Schritt gilt spezifisch für die Implementierung von Azure Cosmos DB for Gremlin.
Antwortbeispiel
Dies ist ein mit Anmerkungen versehenes Beispiel für die Ausgabe, die zurückgegeben wird:
Hinweis
Dieses Beispiel enthält Kommentare, mit denen die allgemeine Struktur der Antwort beschrieben wird. Die richtigen executionProfile-Antworten enthalten keine Kommentare.
[
{
// The Gremlin statement that was executed.
"gremlin": "g.V('mary').out().executionProfile()",
// Amount of time in milliseconds that the entire operation took.
"totalTime": 28,
// An array containing metrics for each of the steps that were executed.
// Each Gremlin step will translate to one or more of these steps.
// This list is sorted in order of execution.
"metrics": [
{
// This operation obtains a set of Vertex objects.
// The metrics include: time, percentTime of total execution time, resultCount,
// fanoutFactor, count, size (in bytes) and time.
"name": "GetVertices",
"time": 24,
"annotations": {
"percentTime": 85.71
},
"counts": {
"resultCount": 2
},
"storeOps": [
{
"fanoutFactor": 1,
"count": 2,
"size": 696,
"time": 0.4
}
]
},
{
// This operation obtains a set of Edge objects.
// Depending on the query, these might be directly adjacent to a set of vertices,
// or separate, in the case of an E() query.
//
// The metrics include: time, percentTime of total execution time, resultCount,
// fanoutFactor, count, size (in bytes) and time.
"name": "GetEdges",
"time": 4,
"annotations": {
"percentTime": 14.29
},
"counts": {
"resultCount": 1
},
"storeOps": [
{
"fanoutFactor": 1,
"count": 1,
"size": 419,
"time": 0.67
}
]
},
{
// This operation obtains the vertices that a set of edges point at.
// The metrics include: time, percentTime of total execution time and resultCount.
"name": "GetNeighborVertices",
"time": 0,
"annotations": {
"percentTime": 0
},
"counts": {
"resultCount": 1
}
},
{
// This operation represents the serialization and preparation for a result from
// the preceding graph operations. The metrics include: time, percentTime of total
// execution time and resultCount.
"name": "ProjectOperator",
"time": 0,
"annotations": {
"percentTime": 0
},
"counts": {
"resultCount": 1
}
}
]
}
]
Hinweis
Im executionProfile-Schritt wird die Gremlin-Abfrage ausgeführt. Dies umfasst die Schritte addV
oder addE
, die zur Erstellung führen und mit denen die in der Abfrage angegebenen Änderungen committet werden. Dies führt dazu, dass auch die von der Gremlin-Abfrage generierten Anforderungseinheiten in Rechnung gestellt werden.
Antwortobjekte des Ausführungsprofils
Die Antwort der Funktion „executionProfile()“ führt zu einer Hierarchie mit JSON-Objekten mit der folgenden Struktur:
Gremlin-Vorgangsobjekt: steht für den gesamten Gremlin-Vorgang, der ausgeführt wurde. Es enthält die folgenden Eigenschaften.
gremlin
: die explizite Gremlin-Anweisung, die ausgeführt wurde.totalTime
: die Zeit in Millisekunden für die Ausführung des Schritts.metrics
: ein Array mit allen Cosmos DB-Runtimeoperatoren, die für die Abfrage ausgeführt wurden. Diese Liste ist in der Reihenfolge der Ausführung sortiert.
Cosmos DB-Runtimeoperatoren: steht für die Komponenten des gesamten Gremlin-Vorgangs. Diese Liste ist in der Reihenfolge der Ausführung sortiert. Jedes Objekt enthält die folgenden Eigenschaften:
name
: Name des Operators. Dies ist der Typ des Schritts, der ausgewertet und ausgeführt wurde. Die Tabelle unten enthält weitere Informationen.time
: Zeitraum in Millisekunden, der für einen bestimmten Operator benötigt wurde.annotations
: enthält zusätzliche spezifische Informationen zum ausgeführten Operator.annotations.percentTime
: Prozentsatz des gesamten Zeitraums, der zum Ausführen des spezifischen Operators benötigt wurde.counts
: Anzahl von Objekten, die von diesem Operator über die Speicherebene zurückgegeben wurden. Diese Angabe ist im Skalarwertcounts.resultCount
enthalten.storeOps
: steht für einen Speichervorgang, der eine oder mehrere Partitionen umfassen kann.storeOps.fanoutFactor
: steht für die Anzahl von Partitionen, auf die von diesem spezifischen Speichervorgang zugegriffen wurde.storeOps.count
: steht für die Anzahl von Ergebnissen, die von diesem Speichervorgang zurückgegeben wurden.storeOps.size
: steht für die Größe des Ergebnisses eines bestimmten Speichervorgangs in Byte.
Gremlin-Runtimeoperator für Cosmos DB | BESCHREIBUNG |
---|---|
GetVertices |
In diesem Schritt wird ein Satz mit Objekten, die über Prädikate verfügen, von der Persistenzebene abgerufen. |
GetEdges |
In diesem Schritt werden die Kanten abgerufen, die an eine Gruppe von Scheitelpunkten angrenzen. Dieser Schritt kann zu einem oder mehreren Speichervorgängen führen. |
GetNeighborVertices |
Dieser Schritt enthält die Scheitelpunkte, die mit einer Gruppe von Kanten verbunden sind. Die Kanten enthalten die Partitionsschlüssel und IDs der Quell- und Zielscheitelpunkte. |
Coalesce |
Dieser Schritt gilt jeweils für die Auswertung von zwei Vorgängen, wenn der Gremlin-Schritt coalesce() ausgeführt wird. |
CartesianProductOperator |
In diesem Schritt wird ein kartesisches Produkt zwischen zwei Datasets berechnet. Normalerweise erfolgt die Ausführung jeweils, wenn die Prädikate to() oder from() verwendet werden. |
ConstantSourceOperator |
In diesem Schritt wird ein Ausdruck berechnet, um als Ergebnis einen konstanten Wert zu erhalten. |
ProjectOperator |
Der Schritt umfasst das Vorbereiten und Serialisieren einer Antwort anhand des Ergebnisses der vorherigen Vorgänge. |
ProjectAggregation |
In diesem Schritt wird eine Antwort für einen Aggregatvorgang vorbereitet und serialisiert. |
Hinweis
Diese Liste wird weiter aktualisiert, wenn neue Operatoren hinzugefügt werden.
Beispiele zur Analyse der Antwort eines Ausführungsprofils
Hier sind Beispiele für häufige Optimierungen angegeben, die anhand der Antwort des Ausführungsprofils ermittelt werden können:
- „Blinde“ Auffächerungsabfrage
- Nicht gefilterte Abfrage
Muster von „blinden“ Auffächerungsabfragen
Angenommen, für einen partitionierten Graphen ergibt sich die folgende Antwort eines Ausführungsprofils:
[
{
"gremlin": "g.V('tt0093640').executionProfile()",
"totalTime": 46,
"metrics": [
{
"name": "GetVertices",
"time": 46,
"annotations": {
"percentTime": 100
},
"counts": {
"resultCount": 1
},
"storeOps": [
{
"fanoutFactor": 5,
"count": 1,
"size": 589,
"time": 75.61
}
]
},
{
"name": "ProjectOperator",
"time": 0,
"annotations": {
"percentTime": 0
},
"counts": {
"resultCount": 1
}
}
]
}
]
Hieraus können die folgenden Schlüsse gezogen werden:
- Die Abfrage ist eine Suche nach einer einzelnen ID, da die Gremlin-Anweisung das Muster
g.V('id')
aufweist. - Anhand der Metrik
time
lässt sich erkennen, dass die Latenz dieser Abfrage wahrscheinlich hoch ist, da sie für einen einzelnen Punktlesevorgang über 10 ms beträgt. - Wenn wir uns das
storeOps
-Objekt ansehen, ist erkennbar, dassfanoutFactor
den Wert5
hat. Dies bedeutet, dass von diesem Vorgang auf 5 Partitionen zugegriffen wurde.
Als Schlussfolgerung dieser Analyse können wir festhalten, dass von der ersten Abfrage auf mehr Partitionen als nötig zugegriffen wird. Dies kann geändert werden, indem der Partitionierungsschlüssel in der Abfrage als Prädikat angegeben wird. Dies führt zu einer niedrigeren Latenz und zu geringeren Kosten pro Abfrage. Informieren Sie sich eingehender über die Graphpartitionierung. Eine besser geeignete Abfrage ist g.V('tt0093640').has('partitionKey', 't1001')
.
Muster von nicht gefilterten Abfragen
Vergleichen Sie die folgenden beiden Antworten von Ausführungsprofilen. Der Einfachheit halber verwenden wir in diesen Beispielen einen einzelnen partitionierten Graphen.
Mit der ersten Abfrage werden alle Scheitelpunkte mit der Bezeichnung tweet
abgerufen, und anschließend werden die angrenzenden Scheitelpunkte abgerufen:
[
{
"gremlin": "g.V().hasLabel('tweet').out().executionProfile()",
"totalTime": 42,
"metrics": [
{
"name": "GetVertices",
"time": 31,
"annotations": {
"percentTime": 73.81
},
"counts": {
"resultCount": 30
},
"storeOps": [
{
"fanoutFactor": 1,
"count": 13,
"size": 6819,
"time": 1.02
}
]
},
{
"name": "GetEdges",
"time": 6,
"annotations": {
"percentTime": 14.29
},
"counts": {
"resultCount": 18
},
"storeOps": [
{
"fanoutFactor": 1,
"count": 20,
"size": 7950,
"time": 1.98
}
]
},
{
"name": "GetNeighborVertices",
"time": 5,
"annotations": {
"percentTime": 11.9
},
"counts": {
"resultCount": 20
},
"storeOps": [
{
"fanoutFactor": 1,
"count": 4,
"size": 1070,
"time": 1.19
}
]
},
{
"name": "ProjectOperator",
"time": 0,
"annotations": {
"percentTime": 0
},
"counts": {
"resultCount": 20
}
}
]
}
]
Beachten Sie das Profil derselben Abfrage, aber jetzt mit dem zusätzlichen Filter has('lang', 'en')
, bevor Sie die angrenzenden Scheitelpunkte untersuchen:
[
{
"gremlin": "g.V().hasLabel('tweet').has('lang', 'en').out().executionProfile()",
"totalTime": 14,
"metrics": [
{
"name": "GetVertices",
"time": 14,
"annotations": {
"percentTime": 58.33
},
"counts": {
"resultCount": 11
},
"storeOps": [
{
"fanoutFactor": 1,
"count": 11,
"size": 4807,
"time": 1.27
}
]
},
{
"name": "GetEdges",
"time": 5,
"annotations": {
"percentTime": 20.83
},
"counts": {
"resultCount": 18
},
"storeOps": [
{
"fanoutFactor": 1,
"count": 18,
"size": 7159,
"time": 1.7
}
]
},
{
"name": "GetNeighborVertices",
"time": 5,
"annotations": {
"percentTime": 20.83
},
"counts": {
"resultCount": 18
},
"storeOps": [
{
"fanoutFactor": 1,
"count": 4,
"size": 1070,
"time": 1.01
}
]
},
{
"name": "ProjectOperator",
"time": 0,
"annotations": {
"percentTime": 0
},
"counts": {
"resultCount": 18
}
}
]
}
]
Diese beiden Abfragen haben zum gleichen Ergebnis geführt. Für das erste Ergebnis sind aber mehr Anforderungseinheiten erforderlich, da ein größeres anfängliches Dataset durchlaufen werden musste, bevor die angrenzenden Elemente abgefragt wurden. Es sind Anzeichen für dieses Verhalten zu erkennen, wenn wir die folgenden Parameter beider Antworten vergleichen:
- Der Wert
metrics[0].time
ist in der ersten Antwort höher. Dies ist ein Hinweis darauf, dass die Auflösung dieses einzelnen Schritts länger gedauert hat. - Auch der Wert
metrics[0].counts.resultsCount
ist in der ersten Antwort höher. Dies weist darauf hin, dass das anfängliche Arbeitsdataset größer war.
Nächste Schritte
- Informieren Sie sich über die unterstützten Gremlin-Features von Azure Cosmos DB.
- Informieren Sie sich über die Gremlin-API in Azure Cosmos DB.