Menyetel kueri Gremlin menggunakan explain dan profile - Amazon Neptune

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

Menyetel kueri Gremlin menggunakan explain dan profile

Anda sering dapat menyetel kueri Gremlin Anda di Amazon Neptunus untuk mendapatkan kinerja yang lebih baik, menggunakan informasi yang tersedia untuk Anda dalam laporan yang Anda dapatkan dari penjelasan dan profil Neptunus. APIs Untuk melakukannya, ia membantu untuk memahami bagaimana Neptune memproses traversals Gremlin.

penting

Perubahan dibuat di TinkerPop versi 3.4.11 yang meningkatkan kebenaran bagaimana kueri diproses, tetapi untuk saat ini terkadang dapat berdampak serius pada kinerja kueri.

Misalnya, kueri semacam ini dapat berjalan jauh lebih lambat:

g.V().hasLabel('airport'). order(). by(out().count(),desc). limit(10). out()

Simpul setelah langkah batas sekarang diambil dengan cara yang tidak optimal karena perubahan 3.4.11. TinkerPop Untuk menghindari hal ini, Anda dapat memodifikasi kueri dengan menambahkan langkah penghalang () kapan saja setelahorder().by(). Sebagai contoh:

g.V().hasLabel('airport'). order(). by(out().count(),desc). limit(10). barrier(). out()

TinkerPop 3.4.11 diaktifkan di mesin Neptunus versi 1.0.5.0.

Memahami pemrosesan traversal Gremlin di Neptune

Ketika traversal Gremlin dikirim ke Neptune, ada tiga proses utama yang mengubah traversal menjadi rencana eksekusi yang mendasari untuk dieksekusi mesin. Ketiganya adalah parsing, conversion, dan optimization:

3 proses mengubah kueri Gremlin menjadi rencana eksekusi.

Proses penguraian traversal

Langkah pertama dalam memproses traversal adalah mengurainya ke dalam bahasa yang sama. Di Neptunus, bahasa umum itu adalah serangkaian langkah yang merupakan TinkerPop bagian dari. TinkerPopAPI Masing-masing langkah ini merupakan unit komputasi dalam traversal.

Anda dapat mengirim traversal Gremlin ke Neptune baik sebagai string atau sebagai bytecode. RESTEndpoint dan submit() metode driver klien Java mengirim traversal sebagai string, seperti dalam contoh ini:

client.submit("g.V()")

Aplikasi dan driver bahasa menggunakan varian bahasa Gremlin (GLV) mengirim traversal dalam bytecode.

Proses konversi traversal

Langkah kedua dalam memproses traversal adalah mengubah TinkerPop langkah-langkahnya menjadi serangkaian langkah Neptunus yang dikonversi dan tidak dikonversi. Sebagian besar langkah dalam bahasa kueri Apache TinkerPop Gremlin dikonversi ke langkah-langkah khusus Neptunus yang dioptimalkan untuk dijalankan pada mesin Neptunus yang mendasarinya. Ketika sebuah TinkerPop langkah tanpa ekuivalen Neptunus ditemui dalam traversal, langkah itu dan semua langkah selanjutnya dalam traversal diproses oleh mesin kueri. TinkerPop

Untuk informasi selengkapnya tentang langkah-langkah apa yang dapat dikonversi dalam keadaan apa, lihat Dukungan langkah Gremlin.

Proses optimasi traversal

Langkah terakhir dalam pemrosesan traversal adalah menjalankan serangkaian langkah dikonversi dan non-dikonversi melalui optimizer, untuk mencoba menentukan rencana eksekusi terbaik. Output dari optimasi ini adalah rencana eksekusi yang diproses mesin Neptune.

Menggunakan Neptunus Gremlin untuk menyetel explain API kueri

Penjelasan Neptunus API tidak sama dengan langkah Gremlin. explain() Ia mengembalikan rencana eksekusi akhir yang akan diproses mesin Neptune ketika mengeksekusi kueri. Karena tidak melakukan pemrosesan apa pun, ia mengembalikan rencana yang sama terlepas dari parameter yang digunakan, dan outputnya tidak mengandung statistik tentang eksekusi aktual.

Pertimbangkan traversal sederhana berikut yang menemukan semua vertex bandara untuk Anchorage:

g.V().has('code','ANC')

Ada dua cara Anda dapat menjalankan traversal ini melalui explain API Neptunus. Cara pertama adalah melakukan REST panggilan ke titik akhir penjelasan, seperti ini:

curl -X POST https://your-neptune-endpoint:port/gremlin/explain -d '{"gremlin":"g.V().has('code','ANC')"}'

Cara kedua adalah menggunakan workbench cell magic %%gremlin Neptune dengan parameter explain. Ini melewati traversal yang terkandung dalam badan sel ke explain API Neptunus dan kemudian menampilkan output yang dihasilkan saat Anda menjalankan sel:

%%gremlin explain g.V().has('code','ANC')

explainAPIOutput yang dihasilkan menggambarkan rencana eksekusi Neptunus untuk traversal. Seperti yang bisa Anda lihat pada gambar di bawah ini, rencananya mencakup masing-masing dari 3 langkah dalam alur pemrosesan:

Jelaskan API output untuk traversal Gremlin sederhana.

Penyetelan traversal dengan melihat langkah-langkah yang tidak dikonversi

Salah satu hal pertama yang harus dicari dalam output explain API Neptunus adalah untuk langkah-langkah Gremlin yang tidak dikonversi ke langkah asli Neptunus. Dalam rencana kueri, ketika langkah yang ditemui tidak dapat dikonversi ke langkah asli Neptune, langkah tersebut dan semua langkah berikutnya dalam rencana diproses oleh server Gremlin.

Dalam contoh di atas, semua langkah dalam traversal dikonversi. Mari kita periksa explain API output untuk traversal ini:

g.V().has('code','ANC').out().choose(hasLabel('airport'), values('code'), constant('Not an airport'))

Seperti yang bisa Anda lihat pada gambar di bawah ini, Neptune tidak bisa mengonversi langkah choose():

Jelaskan API output di mana tidak semua langkah dapat dikonversi.

Ada beberapa hal yang dapat Anda lakukan untuk menyetel performa traversal. Yang pertama adalah menulis ulang sedemikian rupa untuk menghilangkan langkah yang tidak dapat dikonversi. Lainnya adalah memindahkan langkah ke akhir traversal sehingga semua langkah lain dapat dikonversi ke yang asli.

Rencana kueri dengan langkah-langkah yang tidak dikonversi tidak selalu perlu disetel. Jika langkah-langkah yang tidak dapat dikonversi berada di akhir traversal, dan terkait dengan bagaimana output diformat alih-alih bagaimana grafik ditraversalkan, langkah mungkin memiliki sedikit efek pada performa.

Hal lain yang harus dicari ketika memeriksa output dari explain API Neptunus adalah langkah-langkah yang tidak menggunakan indeks. Traversal berikut menemukan semua bandara dengan penerbangan yang mendarat di Anchorage:

g.V().has('code','ANC').in().values('code')

Output dari penjelasan API untuk traversal ini adalah:

******************************************************* Neptune Gremlin Explain ******************************************************* Query String ============ g.V().has('code','ANC').in().values('code') Original Traversal ================== [GraphStep(vertex,[]), HasStep([code.eq(ANC)]), VertexStep(IN,vertex), PropertiesStep([code],value)] Converted Traversal =================== Neptune steps: [ NeptuneGraphQueryStep(PropertyValue) { JoinGroupNode { PatternNode[(?1, <~label>, ?2, <~>) . project distinct ?1 .] PatternNode[(?1, <code>, "ANC", ?) . project ask .] PatternNode[(?3, ?5, ?1, ?6) . project ?1,?3 . IsEdgeIdFilter(?6) .] PatternNode[(?3, <~label>, ?4, <~>) . project ask .] PatternNode[(?3, ?7, ?8, <~>) . project ?3,?8 . ContainsFilter(?7 in (<code>)) .] }, annotations={path=[Vertex(?1):GraphStep, Vertex(?3):VertexStep, PropertyValue(?8):PropertiesStep], maxVarId=9} }, NeptuneTraverserConverterStep ] Optimized Traversal =================== Neptune steps: [ NeptuneGraphQueryStep(PropertyValue) { JoinGroupNode { PatternNode[(?1, <code>, "ANC", ?) . project ?1 .], {estimatedCardinality=1} PatternNode[(?3, ?5, ?1, ?6) . project ?1,?3 . IsEdgeIdFilter(?6) .], {estimatedCardinality=INFINITY} PatternNode[(?3, ?7=<code>, ?8, <~>) . project ?3,?8 .], {estimatedCardinality=7564} }, annotations={path=[Vertex(?1):GraphStep, Vertex(?3):VertexStep, PropertyValue(?8):PropertiesStep], maxVarId=9} }, NeptuneTraverserConverterStep ] Predicates ========== # of predicates: 26 WARNING: reverse traversal with no edge label(s) - .in() / .both() may impact query performance

Pesan WARNING di bagian bawah output terjadi karena langkah in() dalam traversal tidak dapat ditangani menggunakan salah satu dari 3 indeks yang Neptune pertahankan (lihat Bagaimana Pernyataan Diindeks di Neptune dan Pernyataan Gremlin di Neptune). Karena langkah in() tidak berisi filter edge, langkah itu tidak dapat diselesaikan menggunakan indeks SPOG, POGS atau GPSO. Sebaliknya, Neptune harus melakukan pemindaian serikat untuk menemukan vertex yang diminta, yang jauh lebih efisien.

Ada dua cara untuk menyetel traversal dalam situasi ini. Yang pertama adalah menambahkan satu atau lebih kriteria penyaringan ke langkah in() sehingga pencarian yang diindeks dapat digunakan untuk menyelesaikan kueri. Untuk contoh di atas, ini mungkin:

g.V().has('code','ANC').in('route').values('code')

Output dari explain API Neptunus untuk traversal yang direvisi tidak lagi berisi pesan: WARNING

******************************************************* Neptune Gremlin Explain ******************************************************* Query String ============ g.V().has('code','ANC').in('route').values('code') Original Traversal ================== [GraphStep(vertex,[]), HasStep([code.eq(ANC)]), VertexStep(IN,[route],vertex), PropertiesStep([code],value)] Converted Traversal =================== Neptune steps: [ NeptuneGraphQueryStep(PropertyValue) { JoinGroupNode { PatternNode[(?1, <~label>, ?2, <~>) . project distinct ?1 .] PatternNode[(?1, <code>, "ANC", ?) . project ask .] PatternNode[(?3, ?5, ?1, ?6) . project ?1,?3 . IsEdgeIdFilter(?6) . ContainsFilter(?5 in (<route>)) .] PatternNode[(?3, <~label>, ?4, <~>) . project ask .] PatternNode[(?3, ?7, ?8, <~>) . project ?3,?8 . ContainsFilter(?7 in (<code>)) .] }, annotations={path=[Vertex(?1):GraphStep, Vertex(?3):VertexStep, PropertyValue(?8):PropertiesStep], maxVarId=9} }, NeptuneTraverserConverterStep ] Optimized Traversal =================== Neptune steps: [ NeptuneGraphQueryStep(PropertyValue) { JoinGroupNode { PatternNode[(?1, <code>, "ANC", ?) . project ?1 .], {estimatedCardinality=1} PatternNode[(?3, ?5=<route>, ?1, ?6) . project ?1,?3 . IsEdgeIdFilter(?6) .], {estimatedCardinality=32042} PatternNode[(?3, ?7=<code>, ?8, <~>) . project ?3,?8 .], {estimatedCardinality=7564} }, annotations={path=[Vertex(?1):GraphStep, Vertex(?3):VertexStep, PropertyValue(?8):PropertiesStep], maxVarId=9} }, NeptuneTraverserConverterStep ] Predicates ========== # of predicates: 26

Pilihan lain jika Anda menjalankan banyak traversals semacam ini adalah untuk menjalankan traversal tersebut dalam sebuah klaster DB Neptune yang memiliki indeks OSGP opsional diaktifkan (lihat Mengaktifkan Indeks OSGP). Mengaktifkan indeks OSGP memiliki kelemahan:

  • Indeks ini harus diaktifkan dalam klaster DB sebelum data dimuat.

  • Tingkat penyisipan untuk vertex dan edge dapat melambat hingga 23%.

  • Penggunaan penyimpanan akan meningkat sekitar 20%.

  • Kueri Baca yang menyebarkan permintaan di semua indeks mungkin telah meningkatkan latensi.

Memiliki indeks OSGP lebih masuk akal untuk serangkaian pola kueri terbatas, tetapi kecuali jika Anda sering menjalankannya, biasanya lebih baik untuk mencoba untuk memastikan bahwa traversals yang Anda tulis dapat diselesaikan menggunakan tiga indeks utama.

Menggunakan jumlah besar predikat

Neptune memperlakukan setiap label edge dan setiap nama properti vertex atau edge yang berbeda dalam grafik Anda sebagai predikat, dan dirancang secara default untuk bekerja dengan jumlah predikat berbeda yang relatif rendah. Bila Anda memiliki lebih dari beberapa ribu predikat dalam data grafik Anda, performa dapat menurun.

Output explain Neptune akan memperingatkan Anda jika hal ini terjadi:

Predicates ========== # of predicates: 9549 WARNING: high predicate count (# of distinct property names and edge labels)

Jika tidak nyaman untuk mengulang pengerjaan model data Anda untuk mengurangi jumlah label dan properti, dan karenanya jumlah predikatnya, cara terbaik untuk menyetel traversal adalah menjalankannya dalam sebuah klaster DB yang memiliki indeks OSGP diaktifkan, seperti yang dibahas di atas.

Menggunakan Neptunus Gremlin untuk menyetel traversal profile API

profileAPINeptunus sangat berbeda dari langkah Gremlin. profile() Seperti explainAPI, outputnya mencakup rencana kueri yang digunakan mesin Neptunus saat mengeksekusi traversal. Selain itu, output profile menyertakan statistik eksekusi aktual untuk traversal, mengingat bagaimana parameternya ditetapkan.

Sekali lagi, ambil traversal sederhana yang menemukan semua vertex bandara untuk Anchorage:

g.V().has('code','ANC')

Seperti halnya explainAPI, Anda dapat memanggil profile API menggunakan REST panggilan:

curl -X POST https://your-neptune-endpoint:port/gremlin/profile -d '{"gremlin":"g.V().has('code','ANC')"}'

Anda juga menggunakan workbench cell magic %%gremlin Neptune dengan parameter profile. Ini melewati traversal yang terkandung dalam badan sel ke profile API Neptunus dan kemudian menampilkan output yang dihasilkan saat Anda menjalankan sel:

%%gremlin profile g.V().has('code','ANC')

profileAPIOutput yang dihasilkan berisi rencana eksekusi Neptunus untuk traversal dan statistik tentang eksekusi rencana, seperti yang Anda lihat pada gambar ini:

Contoh output profile API Neptunus.

Dalam output profile, bagian rencana eksekusi hanya berisi rencana eksekusi akhir untuk traversal, bukan langkah menengahnya. Bagian alur berisi operasi alur fisik yang dilakukan serta waktu aktual (dalam milidetik) yang diperlukan eksekusi traversal. Metrik runtime sangat membantu dalam membandingkan waktu yang diperlukan dua versi traversal yang berbeda saat Anda mengoptimalkan mereka.

catatan

Runtime awal traversal umumnya lebih panjang dari runtime berikutnya, karena yang pertama menyebabkan data yang relevan untuk di-cache.

Bagian ketiga dari output profile berisi statistik eksekusi dan hasil traversal. Untuk melihat bagaimana informasi ini dapat berguna dalam menyetel traversal, pertimbangkan traversal berikut, yang menemukan setiap bandara yang namanya dimulai dengan “Anchora”, dan semua bandara yang dapat dijangkau dalam dua hop dari bandara tersebut, mengembalikan kode bandara, rute penerbangan, dan jarak:

%%gremlin profile g.withSideEffect("Neptune#fts.endpoint", "{your-OpenSearch-endpoint-URL"). V().has("city", "Neptune#fts Anchora~"). repeat(outE('route').inV().simplePath()).times(2). project('Destination', 'Route'). by('code'). by(path().by('code').by('dist'))

Metrik traversal dalam keluaran Neptunus profile API

Set pertama metrik yang tersedia di semua output profile adalah metrik traversal. Ini mirip dengan metrik langkah profile() Gremlin, dengan beberapa perbedaan:

Traversal Metrics ================= Step Count Traversers Time (ms) % Dur ------------------------------------------------------------------------------------------------------------- NeptuneGraphQueryStep(Vertex) 3856 3856 91.701 9.09 NeptuneTraverserConverterStep 3856 3856 38.787 3.84 ProjectStep([Destination, Route],[value(code), ... 3856 3856 878.786 87.07 PathStep([value(code), value(dist)]) 3856 3856 601.359 >TOTAL - - 1009.274 -

Kolom pertama dari tabel traversal-metrik mencantumkan langkah-langkah yang dijalankan oleh traversal. Dua langkah pertama umumnya adalah langkah-langkah khusus Neptune, NeptuneGraphQueryStep dan NeptuneTraverserConverterStep.

NeptuneGraphQueryStep mewakili waktu eksekusi untuk seluruh bagian dari traversal yang dapat dikonversi dan dieksekusi secara native oleh mesin Neptune.

NeptuneTraverserConverterStepmewakili proses mengubah output dari langkah-langkah yang dikonversi menjadi TinkerPop traversers yang memungkinkan langkah-langkah yang tidak dapat dikonversi langkah-langkah, jika ada, untuk diproses, atau untuk mengembalikan hasil dalam format -kompatibel. TinkerPop

Pada contoh di atas, kita memiliki beberapa langkah yang tidak dikonversi, jadi kita melihat bahwa masing-masing TinkerPop langkah ini (ProjectStep,PathStep) kemudian muncul sebagai baris dalam tabel.

Kolom kedua dalam tabelCount,, melaporkan jumlah pelintas yang diwakili yang melewati langkah, sedangkan kolom ketiga,Traversers, melaporkan jumlah pelintas yang melewati langkah itu, seperti yang dijelaskan dalam dokumentasi langkah profil. TinkerPop

Dalam contoh kita ada 3.856 simpul dan 3.856 traversers dikembalikan olehNeptuneGraphQueryStep, dan angka-angka ini tetap sama sepanjang pengolahan yang tersisa karenaProjectStepdanPathStepmemformat hasil, tidak menyaring mereka.

catatan

Tidak seperti TinkerPop, mesin Neptunus tidak mengoptimalkan kinerja dengan menumpuk di langkah-langkahnya. NeptuneGraphQueryStep NeptuneTraverserConverterStep Bulking adalah TinkerPop operasi yang menggabungkan pelintas pada simpul yang sama untuk mengurangi overhead operasional, dan itulah yang menyebabkan dan angka berbeda. Count Traversers Karena bulking hanya terjadi pada langkah-langkah yang didelegasikan Neptunus, dan bukan pada langkah-langkah yang TinkerPop ditangani Neptunus secara asli, kolom dan kolom jarang berbeda. Count Traverser

Kolom Waktu melaporkan jumlah milidetik yang diambil langkah, dan kolom % Dur melaporkan berapa persen dari total waktu pemrosesan yang diambil langkah. Ini adalah metrik yang memberi tahu Anda tempat untuk memfokuskan upaya penyetelan dengan menunjukkan langkah-langkah yang memakan waktu paling lama.

Metrik operasi indeks dalam output profile API Neptunus

Kumpulan metrik lain dalam output API profil Neptunus adalah operasi indeks:

Index Operations ================ Query execution: # of statement index ops: 23191 # of unique statement index ops: 5960 Duplication ratio: 3.89 # of terms materialized: 0

Laporan ini:

  • Jumlah total pencarian indeks.

  • Jumlah pencarian indeks unik yang dilakukan.

  • Rasio total pencarian indeks ke yang unik. Rasio yang lebih rendah menunjukkan redundansi yang lebih sedikit.

  • Jumlah istilah terwujud dari kamus istilah.

Ulangi metrik dalam output Neptunus profile API

Jika traversal Anda menggunakan repeat() seperti pada contoh di atas, maka bagian yang berisi metrik repeat muncul di output profile:

Repeat Metrics ============== Iteration Visited Output Until Emit Next ------------------------------------------------------ 0 2 0 0 0 2 1 53 0 0 0 53 2 3856 3856 3856 0 0 ------------------------------------------------------ 3911 3856 3856 0 55

Laporan ini:

  • Jumlah loop untuk satu baris (kolom Iteration).

  • Jumlah elemen yang dikunjungi oleh loop (kolom Visited).

  • Jumlah elemen yang dioutput oleh loop (kolom Output).

  • Elemen terakhir yang dioutput oleh loop (kolom Until).

  • Jumlah elemen yang dikeluarkan oleh loop (kolom Emit).

  • Jumlah elemen yang dilewatkan dari loop ke loop berikutnya (kolom Next).

Metrik repeat ini sangat membantu dalam memahami faktor percabangan traversal Anda, untuk mendapatkan kesan berapa banyak pekerjaan yang sedang dilakukan oleh database. Anda dapat menggunakan angka-angka ini untuk mendiagnosis masalah performa, terutama ketika traversal yang sama berkinerja berbeda secara dramatis dengan parameter lainnya.

Metrik pencarian teks lengkap dalam output Neptunus profile API

Ketika traversal menggunakan pencarian pencarian teks lengkap, seperti pada contoh di atas, maka bagian yang berisi metrik pencarian teks lengkap (FTS) muncul di output: profile

FTS Metrics ============== SearchNode[(idVar=?1, query=Anchora~, field=city) . project ?1 .], {endpoint=your-OpenSearch-endpoint-URL, incomingSolutionsThreshold=1000, estimatedCardinality=INFINITY, remoteCallTimeSummary=[total=65, avg=32.500000, max=37, min=28], remoteCallTime=65, remoteCalls=2, joinTime=0, indexTime=0, remoteResults=2} 2 result(s) produced from SearchNode above

Ini menunjukkan kueri yang dikirim ke klaster ElasticSearch (ES) dan melaporkan beberapa metrik tentang interaksi yang dapat membantu Anda menentukan masalah kinerja ElasticSearch yang berkaitan dengan penelusuran teks lengkap:

  • Ringkasan informasi tentang panggilan ke ElasticSearch indeks:

    • Jumlah total milidetik yang dibutuhkan oleh semua remoteCalls untuk memenuhi query (total).

    • Jumlah rata-rata milidetik yang dihabiskan dalam a remoteCall (avg).

    • Jumlah minimum milidetik yang dihabiskan dalam a remoteCall (min).

    • Jumlah maksimum milidetik yang dihabiskan dalam a remoteCall (max).

  • Total waktu yang dikonsumsi oleh remoteCalls to ElasticSearch (remoteCallTime).

  • Jumlah remoteCalls dibuat untuk ElasticSearch (remoteCalls).

  • Jumlah milidetik yang dihabiskan dalam gabungan ElasticSearch hasil ()joinTime.

  • Jumlah milidetik yang dihabiskan dalam pencarian indeks (indexTime).

  • Jumlah total hasil yang dikembalikan oleh ElasticSearch (remoteResults).