Gremlin-lekérdezések kiértékelése a végrehajtási profil lépés segítségével

A KÖVETKEZŐKRE VONATKOZIK: Gremlin

Ez a cikk áttekintést nyújt arról, hogyan használható a végrehajtási profil lépése a Gremlin-gráfadatbázisokhoz készült Azure Cosmos DB-hez. Ez a lépés a hibaelhárításhoz és a lekérdezés optimalizálásához nyújt releváns információkat, és kompatibilis minden olyan Gremlin-lekérdezéssel, amelyet egy Cosmos DB Gremlin API-fiókon lehet végrehajtani.

A lépés használatához egyszerűen fűzze hozzá a executionProfile() függvényhívást a Gremlin-lekérdezés végén. A Rendszer végrehajtja a Gremlin-lekérdezést , és a művelet eredménye egy JSON-válaszobjektumot ad vissza a lekérdezés-végrehajtási profillal.

Például:

    // Basic traversal
    g.V('mary').out()

    // Basic traversal with execution profile call
    g.V('mary').out().executionProfile()

A lépés meghívása után a executionProfile() válasz egy JSON-objektum lesz, amely tartalmazza a végrehajtott Gremlin-lépést, a teljes időtartamot és az utasítás által eredményezett Cosmos DB-futtatókörnyezet-operátorok tömbjét.

Megjegyzés

A végrehajtási profil implementációja nincs definiálva az Apache Tinkerpop specifikációjában. Ez a Gremlin implementációjára vonatkozó Azure Cosmos DB-hez tartozik.

Példa válaszra

A következő egy jegyzettel ellátott példa a visszaadandó kimenetre:

Megjegyzés

Ez a példa megjegyzésekkel van elfűzve, amelyek a válasz általános szerkezetét magyarázzák. A tényleges végrehajtásProfile-válasz nem tartalmaz megjegyzéseket.

[
  {
    // 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
        }
      }
    ]
  }
]

Megjegyzés

A executionProfile lépés végrehajtja a Gremlin-lekérdezést. Ide tartoznak a vagy addEa addV lépések, amelyek a létrehozást eredményezik, és véglegesítik a lekérdezésben megadott módosításokat. Ennek eredményeképpen a Gremlin-lekérdezés által létrehozott kérelemegységek is díjat számítanak fel.

Végrehajtási profil válaszobjektumai

A executionProfile() függvény válasza JSON-objektumok hierarchiáját eredményezi a következő struktúrával:

  • Gremlin-műveletobjektum: A végrehajtott teljes Gremlin-műveletet jelöli. A következő tulajdonságokat tartalmazza.

    • gremlin: A végrehajtott explicit Gremlin-utasítás.
    • totalTime: A lépés végrehajtásának ideje ezredmásodpercben.
    • metrics: Egy tömb, amely tartalmazza a lekérdezés teljesítéséhez végrehajtott Cosmos DB-futtatókörnyezeti operátorokat. Ez a lista végrehajtási sorrendben van rendezve.
  • Cosmos DB futtatókörnyezeti operátorok: A teljes Gremlin-művelet összes összetevőjét jelöli. Ez a lista végrehajtási sorrendben van rendezve. Minden objektum a következő tulajdonságokat tartalmazza:

    • name: Az operátor neve. Ez a kiértékelt és végrehajtott lépés típusa. További információt az alábbi táblázatban talál.
    • time: Az adott operátor által igénybe vett idő ezredmásodpercben.
    • annotations: További információkat tartalmaz, amelyek a végrehajtott operátorra vonatkoznak.
    • annotations.percentTime: Az adott operátor végrehajtásához felhasznált teljes idő százalékos aránya.
    • counts: Az operátor által a tárolási rétegből visszaadott objektumok száma. Ez a benne lévő skaláris értékben counts.resultCount található.
    • storeOps: Olyan tárolási műveletet jelöl, amely egy vagy több partícióra is kiterjedhet.
    • storeOps.fanoutFactor: Az adott tárolási művelet által elért partíciók számát jelöli.
    • storeOps.count: A tárolási művelet által visszaadott eredmények számát jelöli.
    • storeOps.size: Egy adott tárolási művelet eredményének bájtban megadott méretét jelöli.
Cosmos DB Gremlin futtatókörnyezeti operátor Description
GetVertices Ez a lépés egy előre meghatározott objektumkészletet szerez be a perzisztenciarétegből.
GetEdges Ez a lépés lekérte a csúcsok halmazával szomszédos éleket. Ez a lépés egy vagy több tárolási műveletet eredményezhet.
GetNeighborVertices Ez a lépés beolvasja az élkészlethez csatlakoztatott csúcsokat. Az élek tartalmazzák a partíciókulcsokat és a forrás és a cél csúcspontjaik azonosítóját is.
Coalesce Ez a lépés két művelet kiértékelését adja meg a coalesce() Gremlin-lépés végrehajtásakor.
CartesianProductOperator Ez a lépés egy cartesian terméket számít ki két adathalmaz között. Általában akkor hajtják végre, amikor a predikátumokat használják to()from() vagy használják.
ConstantSourceOperator Ez a lépés kiszámít egy kifejezést, amely ennek eredményeként állandó értéket hoz létre.
ProjectOperator Ez a lépés előkészíti és szerializálja a választ az előző műveletek eredményei alapján.
ProjectAggregation Ez a lépés előkészíti és szerializálja a választ egy összesítő művelethez.

Megjegyzés

Ez a lista az új operátorok hozzáadásakor is frissül.

Példák végrehajtásiprofil-válasz elemzésére

Az alábbiakban olyan gyakori optimalizálásokat mutatunk be, amelyeket a végrehajtási profil válaszával lehet észlelni:

  • Vak kifúvatott lekérdezés.
  • Szűretlen lekérdezés.

Vak kifúvatási lekérdezési minták

Tegyük fel, hogy a következő végrehajtásiprofil-válasz particionált gráfból származik:

[
  {
    "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
        }
      }
    ]
  }
]

Ebből a következő következtetések vonhatók le:

  • A lekérdezés egyetlen azonosítókeresés, mivel a Gremlin-utasítás a mintát g.V('id')követi.
  • A metrika alapján time úgy tűnik, hogy a lekérdezés késése magas, mivel több mint 10 ms egy pontolvasási művelethez.
  • Ha megnézzük az storeOps objektumot, láthatjuk, hogy az fanoutFactor , 5ami azt jelenti, hogy ez a művelet 5 partícióhoz fért hozzá.

Ennek az elemzésnek a következtetéseként megállapíthatjuk, hogy az első lekérdezés a szükségesnél több partícióhoz fér hozzá. Ez megoldható úgy, hogy predikátumként megadja a partíciókulcsot a lekérdezésben. Ez kevesebb késéshez és lekérdezésenkénti költséghez vezet. További információ a gráfparticionálásról. Optimálisabb lekérdezés lenne.g.V('tt0093640').has('partitionKey', 't1001')

Szűretlen lekérdezési minták

Hasonlítsa össze az alábbi két végrehajtásiprofil-választ. Az egyszerűség kedvéért ezek a példák egyetlen particionált gráfot használnak.

Ez az első lekérdezés lekéri az összes csúcspontot a címkével tweet , majd lekéri a szomszédos csúcspontokat:

[
  {
    "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
        }
      }
    ]
  }
]

A szomszédos csúcsok felfedezése előtt figyelje meg ugyanannak a lekérdezésnek a profilját, has('lang', 'en')de most egy további szűrővel:

[
  {
    "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
        }
      }
    ]
  }
]

Ez a két lekérdezés ugyanazt az eredményt érte el, azonban az elsőhöz több kérelemegységre lesz szükség, mivel nagyobb kezdeti adatkészletet kellett iterálnia a szomszédos elemek lekérdezése előtt. Ennek a viselkedésnek a mutatóit láthatjuk, amikor összehasonlítjuk a következő paramétereket mindkét válaszból:

  • Az metrics[0].time érték magasabb az első válaszban, ami azt jelzi, hogy ez az egyetlen lépés hosszabb ideig tartott.
  • Az metrics[0].counts.resultsCount érték az első válaszban is magasabb, ami azt jelzi, hogy a kezdeti munkaadatkészlet nagyobb volt.

Következő lépések