Menyelaraskan performa kueri dengan Azure Cosmos DB
BERLAKU UNTUK: NoSQL
Azure Cosmos DB menyediakan API untuk NoSQL untuk mengkueri data, tanpa memerlukan skema atau indeks sekunder. Artikel ini menyediakan informasi berikut ini untuk pengembang:
- Detail tingkat tinggi tentang cara kerja eksekusi kueri SQL Azure Cosmos DB
- Tips dan praktik terbaik untuk performa kueri
- Contoh cara menggunakan metrik eksekusi kueri SQL untuk men-debug performa kueri
Tentang eksekusi kueri SQL
Dalam data Azure Cosmos DB disimpan dalam kontainer, yang dapat tumbuh ke ukuran penyimpanan atau throughput permintaan apa pun. Azure Cosmos DB menskalakan data dengan mulus di seluruh partisi fisik di bawah penutup untuk menangani pertumbuhan data atau peningkatan throughput yang disediakan. Anda dapat mengeluarkan kueri SQL ke kontainer apa pun menggunakan REST API atau salah satu SQL SDK yang didukung.
Ikhtisar singkat pemartisian: Anda mendefinisikan kunci partisi seperti "kota", yang menentukan bagaimana data dibagi di seluruh partisi fisik. Data milik kunci partisi tunggal (misalnya, "kota" == "Seattle") disimpan dalam partisi fisik, dan satu partisi fisik dapat menyimpan data dari beberapa kunci partisi. Ketika partisi mencapai batas penyimpanannya, layanan dengan mulus membagi partisi menjadi dua partisi baru. Data didistribusikan secara merata di seluruh partisi baru, menyimpan semua data untuk satu kunci partisi bersama-sama. Karena partisi bersifat sementara, API menggunakan abstraksi rentang kunci partisi, yang menunjukkan rentang hash kunci partisi.
Saat Anda mengeluarkan kueri ke Azure Cosmos DB, SDK melakukan langkah-langkah logis ini:
- Memilah kueri SQL untuk menentukan rencana eksekusi kueri.
- Jika kueri menyertakan filter terhadap kunci partisi, seperti
SELECT * FROM c WHERE c.city = "Seattle"
, kueri akan dirutekan ke satu partisi. Jika kueri tidak memiliki filter pada kunci partisi, maka kueri dijalankan di semua partisi dan hasil dari setiap partisi digabungkan dengan sisi klien. - Kueri dijalankan dalam setiap partisi secara seri atau paralel, sesuai dengan konfigurasi klien. Dalam setiap partisi, kueri mungkin membuat satu atau lebih perjalanan pulang pergi tergantung pada kompleksitas kueri, ukuran halaman yang dikonfigurasi, dan throughput yang tersedia dari kumpulan. Setiap eksekusi mengembalikan jumlah unit permintaan yang digunakan oleh eksekusi kueri dan statistik eksekusi kueri.
- SDK melakukan ringkasan hasil kueri di seluruh partisi. Misalnya, jika kueri melibatkan ORDER BY di seluruh partisi, hasil dari partisi individual digabungkan dan diurutkan untuk mengembalikan hasil dalam urutan yang diurutkan secara global. Jika kueri adalah agregasi seperti
COUNT
, perhitungan partisi individual dijumlahkan untuk menghasilkan total keseluruhan.
SDK menyediakan berbagai opsi untuk eksekusi kueri. Misalnya, di .NET opsi ini tersedia di kelas QueryRequestOptions
. Tabel berikut ini menjelaskan opsi ini dan bagaimana hal tersebut memengaruhi waktu eksekusi kueri.
Opsi | Deskripsi |
---|---|
EnableScanInQuery |
Hanya berlaku jika pengindeksan untuk jalur filter yang diminta dinonaktifkan. Harus diatur ke true jika Anda memilih keluar dari pengindeksan dan ingin menjalankan kueri menggunakan pemindaian penuh. |
MaxItemCount |
Jumlah maksimum item yang akan dikembalikan per perjalanan pulang pergi ke server. Anda dapat mengaturnya ke -1 untuk membiarkan server mengelola jumlah item yang akan dikembalikan. |
MaxBufferedItemCount |
Jumlah maksimum item yang dapat di-buffer sisi klien selama eksekusi kueri paralel. Nilai properti positif membatasi jumlah item yang di-buffer ke nilai yang ditetapkan. Anda dapat mengaturnya ke kurang dari 0 untuk memungkinkan sistem secara otomatis memutuskan jumlah item ke buffer. |
MaxConcurrency |
Mendapatkan atau mengatur jumlah operasi bersamaan yang menjalankan sisi klien selama eksekusi kueri paralel. Nilai properti positif membatasi jumlah operasi bersamaan dengan nilai yang ditetapkan. Anda dapat mengaturnya ke kurang dari 0 untuk membiarkan sistem secara otomatis memutuskan jumlah operasi bersamaan yang akan dijalankan. |
PopulateIndexMetrics |
Memungkinkan pengumpulan metrik indeks untuk memahami bagaimana mesin kueri menggunakan indeks yang ada dan bagaimana hal itu dapat menggunakan indeks baru potensial. Opsi ini menimbulkan overhead, sehingga hanya boleh diaktifkan saat men-debug kueri lambat. |
ResponseContinuationTokenLimitInKb |
Anda dapat membatasi ukuran maksimum token berkelanjutan yang dikembalikan oleh server. Anda mungkin perlu mengatur ini jika host aplikasi Anda memiliki batasan pada ukuran header respons, tetapi dapat meningkatkan durasi keseluruhan dan RU yang digunakan untuk kueri. |
Misalnya, berikut adalah kueri pada kontainer yang dipartisi dengan /city
menggunakan .NET SDK:
QueryDefinition query = new QueryDefinition("SELECT * FROM c WHERE c.city = 'Seattle'");
QueryRequestOptions options = new QueryRequestOptions()
{
MaxItemCount = -1,
MaxBufferedItemCount = -1,
MaxConcurrency = -1,
PopulateIndexMetrics = true
};
FeedIterator<dynamic> feedIterator = container.GetItemQueryIterator<dynamic>(query);
FeedResponse<dynamic> feedResponse = await feedIterator.ReadNextAsync();
Setiap eksekusi kueri sesuai dengan REST API POST
dengan header yang diatur untuk opsi permintaan kueri dan kueri SQL dalam isi. Untuk detail tentang header dan opsi permintaan REST API, lihat Mengkueri sumber daya menggunakan REST API.
Praktik terbaik untuk performa kueri
Faktor-faktor berikut biasanya memiliki efek terbesar pada performa kueri Azure Cosmos DB. Kami menggali lebih dalam ke masing-masing faktor ini dalam artikel ini.
Kecil | Tip |
---|---|
Throughput yang disediakan | Ukur RU per kueri, dan pastikan Anda memiliki throughput tersedia yang diperlukan untuk kueri Anda. |
Kunci partisi dan pemartisian | Izinkan kueri dengan nilai kunci partisi dalam klausul filter untuk latensi rendah. |
Opsi SDK dan kueri | Ikuti praktik terbaik SDK seperti konektivitas langsung, dan sesuaikan opsi eksekusi kueri pihak klien. |
Latensi jaringan | Jalankan aplikasi Anda di wilayah yang sama dengan akun Azure Cosmos DB Anda sedapat mungkin untuk mengurangi latensi. |
Kebijakan pengindeksan | Pastikan Anda memiliki jalur/kebijakan pengindeksan yang diperlukan untuk kueri. |
Metrik eksekusi kueri | Menganalisis metrik eksekusi kueri untuk mengidentifikasi potensi regenerasi bentuk kueri dan data. |
Throughput yang disediakan
Di Azure Cosmos DB, Anda membuat kontainer data, masing-masing dengan throughput khusus yang dinyatakan dalam unit permintaan (RU) per detik. Baca dokumen 1 KB adalah satu RU, dan setiap operasi (termasuk kueri) dinormalisasi ke sejumlah RU tetap berdasarkan kompleksitasnya. Misalnya, jika Anda memiliki 1000 RU/s yang disediakan untuk kontainer Anda, dan Anda memiliki kueri seperti SELECT * FROM c WHERE c.city = 'Seattle'
yang menggunakan 5 RU, maka Anda dapat menjalankan (1000 RU/dtk) / (5 RU/kueri) = 200 kueri ini per detik.
Jika Anda mengirimkan lebih dari 200 kueri/detik (atau beberapa operasi lain yang menjenuhkan semua RU yang disediakan), layanan memulai permintaan masuk pembatasan tarif. SDK secara otomatis menangani pembatasan laju dengan melakukan backoff/coba lagi, oleh karena itu Anda mungkin melihat latensi yang lebih tinggi untuk kueri ini. Meningkatkan throughput yang disediakan ke nilai yang diperlukan akan meningkatkan latensi dan throughput kueri Anda.
Untuk mempelajari selengkapnya tentang unit permintaan, lihat Unit permintaan.
Kunci partisi dan pemartisian
Dengan Azure Cosmos DB, skenario berikut untuk membaca data diurutkan dari apa yang biasanya tercepat/paling efisien hingga yang paling lambat/paling tidak efisien.
- GET pada kunci partisi tunggal dan id item, juga dikenal sebagai titik baca
- Kueri dengan klausul filter pada satu kunci partisi
- Kueri dengan klausa filter kesetaraan atau rentang pada properti apa pun
- Kueri tanpa filter
Kueri yang perlu dijalankan pada semua partisi memiliki latensi yang lebih tinggi, dan dapat menggunakan RU yang lebih tinggi. Karena setiap partisi memiliki pengindeksan otomatis terhadap semua properti, kueri dapat disajikan secara efisien dari indeks dalam kasus ini. Anda dapat membuat kueri yang mencakup partisi lebih cepat menggunakan opsi paralelisme.
Untuk mempelajari lebih lanjut tentang partisi dan kunci partisi, lihat Pemartisian di Azure Cosmos DB.
Opsi SDK dan kueri
Lihat tips performa kueri dan pengujian performa untuk cara mendapatkan performa sisi klien terbaik dari Azure Cosmos DB menggunakan SDK kami.
Latensi jaringan
Lihat Distribusi global Azure Cosmos DB untuk cara menyiapkan distribusi global dan menyambungkan ke wilayah terdekat. Latensi jaringan memiliki efek signifikan pada performa kueri saat Anda perlu melakukan beberapa perjalanan pulang pergi atau mengambil kumpulan hasil besar dari kueri.
Anda dapat menggunakan metrik eksekusi kueri untuk mengambil waktu eksekusi server kueri, memungkinkan Anda membedakan waktu yang dihabiskan dalam eksekusi kueri dari waktu yang dihabiskan dalam transit jaringan.
Kebijakan pengindeksan
Lihat mengonfigurasi kebijakan pengindeksan untuk mengindeks jalur, jenis, dan mode, dan bagaimana dampaknya terhadap eksekusi kueri. Secara default, Azure Cosmos DB menerapkan pengindeksan otomatis ke semua data dan menggunakan indeks rentang untuk string dan angka, yang efektif untuk kueri kesetaraan. Untuk skenario sisipan performa tinggi, pertimbangkan untuk mengecualikan jalur untuk mengurangi biaya RU untuk setiap operasi penyisipan.
Anda dapat menggunakan metrik indeks untuk mengidentifikasi indeks mana yang digunakan untuk setiap kueri dan jika ada indeks yang hilang yang akan meningkatkan performa kueri.
Metrik eksekusi kueri
Metrik terperinci dikembalikan untuk setiap eksekusi kueri dalam Diagnostik untuk permintaan tersebut. Metrik ini menjelaskan di mana waktu dihabiskan selama eksekusi kueri dan mengaktifkan pemecahan masalah tingkat lanjut.
Pelajari selengkapnya tentang mendapatkan metrik kueri.
Metrik | Unit | Deskripsi |
---|---|---|
TotalTime |
milliseconds | Total waktu eksekusi kueri |
DocumentLoadTime |
milliseconds | Waktu yang dihabiskan untuk memuat dokumen |
DocumentWriteTime |
milliseconds | Waktu yang dihabiskan untuk menulis dan membuat serial dokumen output |
IndexLookupTime |
milliseconds | Waktu yang dihabiskan dalam lapisan indeks fisik |
QueryPreparationTime |
milliseconds | Waktu yang dihabiskan dalam menyiapkan kueri |
RuntimeExecutionTime |
milliseconds | Total waktu eksekusi runtime kueri |
VMExecutionTime |
milliseconds | Waktu yang dihabiskan dalam runtime kueri yang menjalankan kueri |
OutputDocumentCount |
jumlah | Jumlah dokumen output dalam tataan hasil |
OutputDocumentSize |
jumlah | Ukuran total dokumen yang dihasilkan dalam byte |
RetrievedDocumentCount |
jumlah | Jumlah total dokumen yang diambil |
RetrievedDocumentSize |
byte | Ukuran total dokumen yang diambil dalam format byte |
IndexHitRatio |
rasio [0,1] | Rasio jumlah dokumen yang cocok dengan filter dengan jumlah dokumen yang dimuat |
SDK klien dapat secara internal membuat beberapa permintaan kueri untuk melayani kueri dalam setiap partisi. Klien melakukan lebih dari satu panggilan per partisi jika hasil total melebihi opsi permintaan jumlah item maksimum, jika kueri melebihi throughput yang disediakan untuk partisi, jika payload kueri mencapai ukuran maksimum per halaman, atau jika kueri mencapai batas waktu habis yang dialokasikan sistem. Setiap eksekusi kueri parsial mengembalikan metrik kueri untuk halaman tersebut.
Berikut adalah beberapa contoh kueri dan cara menginterpretasikan beberapa metrik yang dikembalikan dari eksekusi kueri:
Kueri | Metrik Contoh | Deskripsi |
---|---|---|
SELECT TOP 100 * FROM c |
"RetrievedDocumentCount": 101 |
Jumlah dokumen yang diambil adalah 100+1 untuk mencocokkan klausul TOP. Waktu kueri sebagian besar dihabiskan dan WriteOutputTime DocumentLoadTime karena ini adalah pemindaian. |
SELECT TOP 500 * FROM c |
"RetrievedDocumentCount": 501 |
RetrievedDocumentCount sekarang lebih tinggi (500+1 untuk mencocokkan klausul TOP). |
SELECT * FROM c WHERE c.N = 55 |
"IndexLookupTime": "00:00:00.0009500" |
Sekitar 0,9 ms dihabiskan di IndexLookupTime untuk pencarian kunci, karena ini adalah pencarian indeks di /N/? . |
SELECT * FROM c WHERE c.N > 55 |
"IndexLookupTime": "00:00:00.0017700" |
Sedikit lebih banyak waktu (1,7 ms) dihabiskan di IndexLookupTime selama pemindaian rentang, karena ini adalah pencarian indeks di /N/? . |
SELECT TOP 500 c.N FROM c |
"IndexLookupTime": "00:00:00.0017700" |
Waktu yang sama dihabiskan DocumentLoadTime seperti kueri sebelumnya, tetapi lebih rendah DocumentWriteTime karena hanya satu properti yang diproyeksikan. |
SELECT TOP 500 udf.toPercent(c.N) FROM c |
"RuntimeExecutionTime": "00:00:00.2136500" |
Sekitar 213 ms dihabiskan RuntimeExecutionTime dalam mengeksekusi UDF pada setiap nilai c.N . |
SELECT TOP 500 c.Name FROM c WHERE STARTSWITH(c.Name, 'Den') |
"IndexLookupTime": "00:00:00.0006400", "RuntimeExecutionTime": "00:00:00.0074100" |
Sekitar 0,6 ms dihabiskan di IndexLookupTime pada /Name/? . Sebagian besar waktu eksekusi kueri (–7 ms) di RuntimeExecutionTime . |
SELECT TOP 500 c.Name FROM c WHERE STARTSWITH(LOWER(c.Name), 'den') |
"IndexLookupTime": "00:00:00", "RetrievedDocumentCount": 2491, "OutputDocumentCount": 500 |
Kueri difungsikan sebagai pemindaian karena menggunakan LOWER , dan 500 dari 2491 dokumen yang diambil dikembalikan. |
Langkah berikutnya
- Untuk mempelajari tentang operator dan kata kunci kueri SQL yang didukung, lihat kueri SQL.
- Untuk mempelajari tentang unit permintaan, lihat Unit permintaan.
- Untuk mempelajari tentang kebijakan pengindeksan, lihat kebijakan pengindeksan