Bagikan melalui


Cara menggunakan langkah profil eksekusi untuk mengevaluasi kueri Gremlin Anda

BERLAKU UNTUK: Gremlin

Artikel ini memberikan gambaran umum tentang cara menggunakan langkah profil eksekusi untuk database grafik Azure Cosmos DB untuk Gremlin. Langkah ini memberikan informasi yang relevan untuk pemecahan masalah dan pengoptimalan kueri, dan kompatibel dengan kueri Gremlin apa pun yang dapat dieksekusi terhadap akun Cosmos DB Gremlin API.

Untuk menggunakan langkah ini, cukup tambahkan executionProfile() panggilan fungsi di akhir kueri Gremlin Anda. Kueri Gremlin Anda akan dijalankan dan hasil operasi akan mengembalikan objek respons JSON dengan profil eksekusi kueri.

Contohnya:

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

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

Setelah memanggil langkah executionProfile(), respons akan menjadi objek JSON yang mencakup langkah Gremlin yang dijalankan, total waktu yang diperlukan, dan larik operator runtime Cosmos DB yang dihasilkan oleh pernyataan tersebut.

Catatan

Implementasi untuk Profil Eksekusi ini tidak didefinisikan dalam spesifikasi Apache Tinkerpop. Ini khusus untuk Azure Cosmos DB untuk implementasi Gremlin.

Contoh Tanggapan

Berikut ini adalah contoh anotasi output yang akan dikembalikan:

Catatan

Contoh ini dianotasikan dengan komentar yang menjelaskan struktur umum respons. Respons aktual executionProfile tidak akan berisi komentar apa pun.

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

Catatan

Langkah executionProfile akan menjalankan kueri Gremlin. Ini mencakup langkah addV atau addE, yang akan menghasilkan pembuatan dan akan menerapkan perubahan yang ditentukan dalam kueri. Akibatnya, Unit Permintaan yang dihasilkan oleh kueri Gremlin juga akan dikenakan biaya.

Objek respons profil eksekusi

Respons fungsi executionProfile() akan menghasilkan hierarki objek JSON dengan struktur berikut:

  • Objek operasi Gremlin: Mewakili seluruh operasi Gremlin yang dijalankan. Berisi properti berikut.

    • gremlin: Pernyataan eksplisit Gremlin yang dijalankan.
    • totalTime: Waktu (dalam satuan milidetik) saat eksekusi langkah tersebut terjadi.
    • metrics: Larik yang berisi masing-masing operator runtime Cosmos DB yang dieksekusi untuk memenuhi kueri. Daftar ini diurutkan dalam urutan eksekusi.
  • Operator runtime Cosmos DB: Mewakili masing-masing komponen dari seluruh operasi Gremlin. Daftar ini diurutkan dalam urutan eksekusi. Setiap objek berisi properti berikut:

    • name: Nama operator. Ini adalah jenis langkah yang dievaluasi dan dijalankan. Baca selengkapnya dalam tabel di bawah ini.
    • time: Jumlah waktu (dalam milidetik) yang diambil operator tertentu.
    • annotations: Berisi informasi tambahan, khususnya untuk operator yang dijalankan.
    • annotations.percentTime: Persentase dari total waktu yang diperlukan untuk mengeksekusi operator tertentu.
    • counts: Jumlah objek yang dikembalikan dari lapisan penyimpanan oleh operator ini. Ini terkandung dalam nilai skalar counts.resultCount di dalamnya.
    • storeOps: Mewakili operasi penyimpanan yang dapat mencakup satu atau beberapa partisi.
    • storeOps.fanoutFactor: Mewakili jumlah partisi yang diakses operasi penyimpanan khusus ini.
    • storeOps.count: Mewakili jumlah hasil yang dikembalikan operasi penyimpanan ini.
    • storeOps.size: Mewakili ukuran dalam byte hasil operasi penyimpanan yang diberikan.
Operator Runtime Cosmos DB Gremlin Deskripsi
GetVertices Langkah ini memperoleh sekumpulan objek yang diprediksikan dari lapisan persistensi.
GetEdges Langkah ini mendapatkan tepi yang berdekatan dengan satu set sudut. Langkah ini dapat menghasilkan satu atau beberapa operasi penyimpanan.
GetNeighborVertices Langkah ini mendapatkan sudut yang terhubung ke seperangkat tepi. Tepi berisi kunci partisi dan ID dari sudut sumber dan targetnya.
Coalesce Langkah ini memperhitungkan evaluasi dua operasi setiap kali langkah Gremlin coalesce() dijalankan.
CartesianProductOperator Langkah ini menghitung produk Kartesius antara dua himpunan data. Biasanya dieksekusi setiap kali predikat to() atau from() digunakan.
ConstantSourceOperator Langkah ini menghitung ekspresi untuk menghasilkan nilai konstanta.
ProjectOperator Langkah ini mempersiapkan dan mengurutkan respons berdasarkan hasil operasi sebelumnya.
ProjectAggregation Langkah ini mempersiapkan dan mengurutkan respons untuk operasi agregat.

Catatan

Daftar ini akan terus diperbarui seiring ditambahkannya operator baru.

Contoh cara menganalisis respons profil eksekusi

Berikut ini adalah contoh pengoptimalan umum yang dapat dilihat dengan menggunakan respons Profil Eksekusi:

  • Kueri blind fan-out.
  • Kueri yang tidak difilter.

Pola kueri blind fan-out

Asumsikan respons profil eksekusi berikut dari grafik yang dipartisi:

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

Kesimpulan yang dapat ditarik adalah sebagai berikut:

  • Kueri adalah pencarian ID tunggal, karena pernyataan Gremlin selalu mengikuti pola g.V('id').
  • Dilihat dari metrik time, latensi kueri ini terlihat tinggi karena lebih dari 10ms untuk satu operasi baca titik.
  • Jika kita mengamati objek storeOps, kita dapat melihat bahwa fanoutFactor adalah 5, yang berarti bahwa 5 partisi diakses oleh operasi ini.

Sebagai kesimpulan dari analisis ini, kita dapat menentukan bahwa kueri pertama mengakses lebih banyak partisi daripada yang diperlukan. Ini dapat diatasi dengan menentukan kunci partisi dalam kueri sebagai predikat. Ini akan mengurangi latensi dan biaya per kueri. Pelajari selengkapnya tentang pemartisian grafik. Kueri yang lebih optimal adalah g.V('tt0093640').has('partitionKey', 't1001').

Pola kueri tidak difilter

Bandingkan dua respons profil eksekusi berikut. Untuk mempermudah, contoh-contoh ini menggunakan grafik yang dipartisi tunggal.

Kueri pertama ini mengambil semua sudut berlabel tweet, kemudian mendapatkan sudut tetangganya:

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

Perhatikan profil kueri yang sama, tetapi sekarang dengan filter tambahan, has('lang', 'en'), sebelum menjelajahi sudut yang berdekatan:

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

Kedua kueri ini mencapai hasil yang sama, namun, yang pertama akan memerlukan lebih banyak Unit Permintaan (RU) karena RU diperlukan untuk melakukan iterasi himpunan data awal yang lebih besar sebelum mengkueri item yang berdekatan. Kita dapat melihat indikator perilaku ini saat membandingkan parameter berikut dari kedua respons:

  • Nilai metrics[0].time lebih tinggi di respons pertama, yang menunjukkan bahwa langkah tunggal ini membutuhkan waktu penyelesaian yang lebih lama.
  • Nilai metrics[0].counts.resultsCount juga lebih tinggi pada respons pertama, yang menunjukkan bahwa himpunan data kerja awal lebih besar.

Langkah berikutnya