Praktik terbaik kueri grafik
Dokumen ini menjelaskan praktik terbaik untuk mengoptimalkan kueri Grafik BigQuery.
Mulai penelusuran jalur dari node kardinalitas rendah
Untuk menjaga agar set hasil perantara tetap kecil dan mempercepat eksekusi kueri, tulis kueri grafik Anda sehingga penelusuran jalur dimulai dari node kardinalitas yang lebih rendah, terlepas dari arah penelusuran jalur. Pernyataan
MATCH berikut menggunakan filter properti untuk mengurangi jumlah kemungkinan
node awal, bukan menghitung semua kecocokan lalu memfilter:
MATCH (p:Person {id: 10})-[own:Owns]->(a:Account)
MATCH (a:Account WHERE balance > 10)<-[own:Owns]-(p:Person)
Hal ini sangat penting untuk kueri jalur yang dikuantifikasi:
MATCH (p:Person {id: 10})-[own:Owns]->{1,3}(a:Account)
Gunakan sintaks ANY atau ANY SHORTEST untuk pemeriksaan konektivitas
Kueri jalur yang dikuantifikasi dapat menampilkan jalur duplikat antara node sumber dan node tujuan. Jika tujuan Anda adalah memeriksa konektivitas dan Anda tidak
memerlukan semua kemungkinan jalur, gunakan ANY atau ANY SHORTEST untuk mengurangi komputasi
yang berlebihan dan meningkatkan efisiensi pencarian jalur. Misalnya, pernyataan
MATCH berikut menggunakan ANY SHORTEST untuk mempertahankan hanya satu jalur di antara setiap pasangan
node:
MATCH ANY SHORTEST (a1:Account)-[t:Transfers]->{1,3}(a2:Account)
Menggunakan penelusuran jalur terarah
Skema Grafik BigQuery bersifat terarah, yang berarti bahwa setiap
tepi memiliki node sumber dan node tujuan. Meskipun sintaksis kueri grafik memungkinkan penelusuran jalur ke segala arah (misalnya, -[edge]-), sebaiknya gunakan penelusuran jalur terarah (misalnya, -[edge]-> atau <-[edge]-) untuk performa yang lebih baik. Traversal jalur arah mana pun dapat menyebabkan penurunan performa.
Pernyataan MATCH berikut menggunakan traversal jalur arah mana pun:
-- Avoid.
MATCH (a1:Account {id: 7})-[t:Transfers]-(a2:Account)
Sebagai gantinya, gabungkan dua penelusuran terarah dengan UNION ALL:
MATCH (a1:Account {id: 7})-[t:Transfers]->(a2:Account)
...
UNION ALL
...
MATCH (a1:Account {id: 7})<-[t:Transfers]-(a2:Account)
Menentukan label secara eksplisit
Jika label node atau edge tidak disertakan dalam kueri, BigQuery Graph akan mencantumkan semua label node dan edge yang memenuhi syarat. Enumerasi ini dapat menyebabkan lebih banyak label dipindai daripada yang diperlukan. Untuk menghindari hal ini, tentukan label untuk semua node dan tepi dalam kueri Anda jika memungkinkan.
Misalnya, kueri berikut menentukan label Account dan Transfers:
GRAPH graph_db.FinGraph
MATCH (a1:Account)-[t:Transfers]->(a2:Account)
RETURN COUNT(*) AS num_transfers;
Hindari menghilangkan label, karena dapat memindai hubungan lain yang tidak diperlukan antar-node. Dalam kueri berikut, a1 dapat mewakili akun atau orang, dan t dapat mewakili transfer atau kepemilikan akun.
GRAPH graph_db.FinGraph
MATCH (a1)-[t]->(a2)
RETURN COUNT(*) AS num_transfers;
Lebih memilih satu pernyataan MATCH
BigQuery Graph memungkinkan Anda menyertakan beberapa pernyataan MATCH dalam
satu kueri grafik. Pernyataan ini terhubung oleh variabel yang dideklarasikan beberapa kali
yang merepresentasikan node atau tepi yang sama. Namun, penggunaan beberapa pernyataan MATCH
dapat mengurangi manfaat kardinalitas di seluruh pernyataan. Jika memungkinkan, gunakan satu pernyataan MATCH untuk mendapatkan performa yang lebih baik.
Misalnya, kueri berikut setara, tetapi kueri pertama berperforma lebih baik karena menggunakan satu pernyataan MATCH:
-- Preferred syntax.
GRAPH graph_db.FinGraph
MATCH
(p:Person {id: 1})-[o:Owns]->
(a:Account)-[t:Transfers]->(a2:Account)
RETURN o.account_id, t.amount;
-- Avoid this syntax.
GRAPH graph_db.FinGraph
MATCH (p:Person {id: 1})-[o:Owns]->(a:Account)
MATCH (a:Account)-[t:Transfers]->(a2:Account)
RETURN o.account_id, t.amount;
Membatasi tepi yang dilalui dari node berkardinalitas tinggi
Saat Anda mengkueri grafik, beberapa node dapat memiliki jumlah tepi masuk atau keluar yang jauh lebih besar dibandingkan dengan node lain. Node dengan kardinalitas tinggi ini terkadang disebut node super atau node hub. Node super dapat menyebabkan masalah performa karena penelusuran melalui node tersebut mungkin melibatkan pemrosesan data dalam jumlah besar, yang menyebabkan kemiringan data dan waktu eksekusi yang lama.
Untuk mengoptimalkan kueri grafik dengan node super, gunakan
fungsi ROW_NUMBER()
dalam klausa FILTER atau klausa WHERE di MATCH untuk membatasi
jumlah tepi yang dilalui kueri dari atau ke node. Teknik ini sangat berguna jika Anda tidak memerlukan enumerasi lengkap semua koneksi dari atau ke super node.
Misalnya, jika beberapa akun di FinGraph memiliki banyak transaksi, Anda dapat menggunakan ROW_NUMBER() untuk membatasi jumlah edge Transfers yang akan dipertimbangkan untuk setiap Account dan menghindari kueri yang tidak efisien:
GRAPH graph_db.FinGraph
MATCH (a1:Account)-[e1:Transfers WHERE e1 IN {
GRAPH graph_db.FinGraph
-- Sample 5 edges per source node
MATCH -[selected_e:Transfers]->
FILTER ROW_NUMBER() OVER (
PARTITION BY SOURCE_NODE_ID(selected_e)) < 5
RETURN selected_e
}]->{1,3}(a2:Account)
RETURN COUNT(*) AS cnt;
Contoh node atau edge perantara dalam kueri multi-hop
Anda juga dapat meningkatkan efisiensi kueri dengan menggunakan ROW_NUMBER() untuk mengambil sampel
node perantara dalam kueri multi-hop. Teknik ini meningkatkan efisiensi dengan
membatasi jumlah jalur yang dipertimbangkan kueri untuk setiap node
perantara. Untuk melakukannya, pecah kueri multi-hop menjadi beberapa pernyataan MATCH
yang dipisahkan oleh NEXT, dan terapkan ROW_NUMBER() di titik tengah tempat Anda perlu
melakukan pengambilan sampel:
GRAPH graph_db.FinGraph
MATCH (a1:Account)-[e1:Transfers]->(a2:Account)
-- Sample 5 destination nodes per a1 source node
FILTER ROW_NUMBER() OVER (PARTITION BY ELEMENT_ID(a1)) < 5
RETURN a1, a2
NEXT
MATCH (a2)-[e2:Transfers]->(a3:Account)
RETURN a1.id AS src_id, a2.id AS mid_id, a3.id AS dst_id;
Langkah berikutnya
- Untuk mempelajari lebih lanjut cara menulis kueri grafik, lihat ringkasan kueri.
- Pelajari lebih lanjut praktik terbaik skema.