Mengoptimalkan kueri log di Azure Monitor

Log Azure Monitor menggunakan Azure Data Explorer untuk menyimpan data log dan menjalankan kueri untuk menganalisis data tersebut. Ini membuat, mengelola, dan memelihara kluster Azure Data Explorer untuk Anda, dan mengoptimalkannya untuk beban kerja analisis log Anda. Saat Anda menjalankan kueri, kueri dioptimalkan dan dirutekan ke kluster Azure Data Explorer yang sesuai yang menyimpan data ruang kerja.

Log Azure Monitor dan Azure Data Explorer menggunakan banyak mekanisme pengoptimalan kueri otomatis. Pengoptimalan otomatis memberikan peningkatan yang signifikan, tetapi ada beberapa kasus di mana Anda dapat secara dramatis meningkatkan performa kueri Anda. Artikel ini menjelaskan pertimbangan kinerja dan beberapa teknik untuk memperbaikinya.

Sebagian besar teknik umum untuk kueri yang dijalankan langsung di Azure Data Explorer dan Log Azure Monitor. Beberapa pertimbangan Log Azure Monitor yang unik juga dibahas. Untuk tips pengoptimalan Azure Data Explorer lainnya, lihat Praktik terbaik kueri.

Kueri yang dioptimalkan akan:

  • Jalankan lebih cepat dan kurangi durasi keseluruhan eksekusi kueri.
  • Memiliki peluang lebih kecil untuk dibatasi atau ditolak.

Perhatikan secara khusus kueri yang digunakan untuk penggunaan berulang dan bersamaan, seperti dasbor, pemberitahuan, Azure Logic Apps, dan Power BI. Dampak kueri yang tidak efektif dalam kasus ini bersifat substansial.

Berikut panduan video mendetail tentang mengoptimalkan kueri.

Panel Detail Kueri

Setelah Anda menjalankan kueri di Analitik Log, pilih Detail kueri di sudut kanan bawah layar untuk membuka panel Detail Kueri. Panel ini memperlihatkan hasil beberapa indikator performa untuk kueri. Indikator performa ini dijelaskan di bagian berikut.

Screenshot that shows the Query Details pane in Azure Monitor Log Analytics.

Indikator kinerja kueri

Indikator performa kueri berikut ini tersedia untuk setiap kueri yang dijalankan:

  • Total CPU: Komputasi keseluruhan digunakan untuk memproses kueri di seluruh node komputasi. Hal ini mewakili waktu yang digunakan untuk komputasi, penguraian, dan pengambilan data.
  • Data yang digunakan untuk kueri yang diproses: Data keseluruhan yang diakses untuk memproses kueri. Dipengaruhi oleh ukuran tabel target, rentang waktu yang digunakan, filter yang diterapkan, dan jumlah kolom yang direferensikan.
  • Rentang waktu kueri yang diproses: Selisih antara data terbaru dan terlama yang diakses untuk memproses kueri. Dipengaruhi oleh rentang waktu eksplisit yang ditentukan untuk kueri.
  • Usia data yang diproses: Selisih antara sekarang dan data terlama yang diakses untuk memproses kueri. Selisih ini sangat memengaruhi efisiensi pengambilan data.
  • Jumlah ruang kerja: Berapa banyak ruang kerja yang diakses selama pemrosesan kueri berdasarkan pemilihan implisit atau eksplisit.
  • Jumlah wilayah: Berapa banyak wilayah yang diakses selama pemrosesan kueri berdasarkan pemilihan ruang kerja implisit atau eksplisit. Kueri multi-wilayah jauh lebih efisien, dan indikator performa menyajikan cakupan parsial.
  • Paralelisme: Menunjukkan banyaknya sistem yang mampu menjalankan kueri ini di beberapa node. Hanya relevan dengan kueri yang memiliki konsumsi CPU tinggi. Dipengaruhi oleh penggunaan fungsi dan operator tertentu.

Total CPU

CPU komputasi aktual yang diinvestasikan untuk memproses kueri ini di seluruh node pemrosesan kueri. Karena sebagian besar kueri dijalankan pada sejumlah besar simpul, total ini biasanya akan jauh lebih besar daripada durasi yang diambil kueri untuk dijalankan.

Kueri yang menggunakan CPU lebih dari 100 detik dianggap sebagai kueri yang menggunakan sumber daya yang berlebihan. Kueri yang menggunakan CPU lebih dari 1.000 detik dianggap sebagai kueri yang melecehkan dan mungkin dibatasi.

Waktu pemrosesan kueri dihabiskan untuk:

  • Pengambilan data: Pengambilan data lama akan menghabiskan lebih banyak waktu daripada pengambilan data terbaru.
  • Pemrosesan data: Logika dan evaluasi data.

Selain waktu yang dihabiskan dalam simpul pemrosesan kueri, Log Azure Monitor menghabiskan waktu dalam:

  • Mengautentikasi pengguna dan memverifikasi bahwa mereka diizinkan untuk mengakses data ini.
  • Menemukan penyimpanan data.
  • Mengurai kueri.
  • Mengalokasikan simpul pemrosesan kueri.

Waktu ini tidak termasuk dalam waktu CPU total kueri.

Pemfilteran awal rekaman sebelum menggunakan fungsi CPU tinggi

Beberapa perintah dan fungsi kueri menggunakan konsumsi CPU yang tinggi. Kasus ini terutama berlaku untuk perintah yang mengurai JSON dan XML atau mengekstrak ekspresi reguler yang kompleks. Penguraian tersebut dapat terjadi secara eksplisit melalui fungsi parse_json() atau parse_xml() atau secara implisit ketika mengacu pada kolom dinamis.

Fungsi ini mengonsumsi CPU yang sebanding dengan jumlah baris yang diproses. Pengoptimalan yang paling efisien adalah menambahkan where kondisi di awal kueri. Dengan cara ini, mereka dapat memfilter rekaman sebanyak mungkin sebelum fungsi intensif CPU dijalankan.

Misalnya, kueri berikut menghasilkan hasil yang sama persis. Tetapi yang kedua adalah yang paling efisien karena kondisi di mana sebelum penguraian mengecualikan banyak rekaman:

//less efficient
SecurityEvent
| extend Details = parse_xml(EventData)
| extend FilePath = tostring(Details.UserData.RuleAndFileData.FilePath)
| extend FileHash = tostring(Details.UserData.RuleAndFileData.FileHash)
| where FileHash != "" and FilePath !startswith "%SYSTEM32"  // Problem: irrelevant results are filtered after all processing and parsing is done
| summarize count() by FileHash, FilePath
//more efficient
SecurityEvent
| where EventID == 8002 //Only this event have FileHash
| where EventData !has "%SYSTEM32" //Early removal of unwanted records
| extend Details = parse_xml(EventData)
| extend FilePath = tostring(Details.UserData.RuleAndFileData.FilePath)
| extend FileHash = tostring(Details.UserData.RuleAndFileData.FileHash)
| where FileHash != "" and FilePath !startswith "%SYSTEM32"  // exact removal of results. Early filter is not accurate enough
| summarize count() by FileHash, FilePath
| where FileHash != "" // No need to filter out %SYSTEM32 here as it was removed before

Hindari menggunakan klausul where yang dievaluasi

Kueri yang berisi klausul where pada kolom yang dievaluasi, bukan pada kolom yang ada secara fisik dalam himpunan data, kehilangan efisiensi. Pemfilteran pada kolom yang dievaluasi mencegah beberapa pengoptimalan sistem saat himpunan data besar ditangani.

Misalnya, kueri berikut menghasilkan hasil yang sama persis. Tetapi yang kedua lebih efisien karena kondisi di mana mengacu pada kolom bawaan:

//less efficient
Syslog
| extend Msg = strcat("Syslog: ",SyslogMessage)
| where  Msg  has "Error"
| count 
//more efficient
Syslog
| where  SyslogMessage  has "Error"
| count 

Dalam beberapa kasus, kolom yang dievaluasi dibuat secara implisit oleh mesin pemrosesan kueri karena pemfilteran dilakukan tidak hanya pada bidang:

//less efficient
SecurityEvent
| where tolower(Process) == "conhost.exe"
| count 
//more efficient
SecurityEvent
| where Process =~ "conhost.exe"
| count 

Gunakan perintah agregasi dan dimensi yang efektif dalam meringkas dan melakukan penggabungan

Beberapa perintah agregasi seperti max(), sum(), count(), dan avg() memiliki dampak CPU yang rendah karena logikanya. Perintah lain lebih kompleks dan mencakup heuristik dan estimasi yang memungkinkannya dijalankan secara efisien. Misalnya, dcount() menggunakan algoritma HyperLogLog untuk memberikan estimasi yang dekat dengan jumlah data yang berbeda tanpa benar-benar menghitung setiap nilai.

Fungsi persentil melakukan perkiraan serupa dengan menggunakan algoritma persentil peringkat terdekat. Beberapa perintah termasuk parameter opsional untuk mengurangi dampaknya. Misalnya, fungsi makeset() memiliki parameter opsional untuk menentukan ukuran set maksimum, yang secara signifikan memengaruhi CPU dan memori.

Menggabungkan dan meringkas perintah dapat menyebabkan pemanfaatan CPU yang tinggi saat memproses sekumpulan data yang besar. Kompleksitasnya terkait langsung dengan jumlah nilai yang mungkin, disebut sebagai kardinalitas, dari kolom yang digunakan sebagai by dalam summarize atau sebagai join atribut. Untuk penjelasan dan pengoptimalan join dan summarize, lihat artikel dokumentasi dan tips pengoptimalannya.

Misalnya, kueri berikut menghasilkan hasil yang sama persis karena CounterPath selalu satu-ke-satu dipetakan ke CounterName dan ObjectName. Yang kedua lebih efisien karena dimensi agregasi lebih kecil:

//less efficient
Perf
| summarize avg(CounterValue) 
by CounterName, CounterPath, ObjectName
//make the group expression more compact improve the performance
Perf
| summarize avg(CounterValue), any(CounterName), any(ObjectName) 
by CounterPath

Konsumsi CPU mungkin juga dipengaruhi oleh where kondisi atau kolom yang diperluas yang memerlukan komputasi intensif. Semua perbandingan string sepele, seperti equal == dan startswith, memiliki dampak CPU yang kira-kira sama. Kecocokan teks tingkat lanjut memiliki dampak lebih besar. Secara khusus, operator has lebih efisien daripada operator berisi . Karena teknik penanganan string, lebih efisien untuk mencari string yang lebih panjang dari empat karakter daripada string pendek.

Misalnya, kueri berikut menghasilkan hasil yang sama, tergantung pada Computer kebijakan penamaan. Tetapi yang kedua lebih efisien:

//less efficient – due to filter based on contains
Heartbeat
| where Computer contains "Production" 
| summarize count() by ComputerIP 
//less efficient – due to filter based on extend
Heartbeat
| extend MyComputer = Computer
| where MyComputer startswith "Production" 
| summarize count() by ComputerIP 
//more efficient
Heartbeat
| where Computer startswith "Production" 
| summarize count() by ComputerIP 

Catatan

Indikator ini hanya menyajikan CPU dari kluster langsung. Dalam kueri multi-wilayah, kueri hanya akan mewakili salah satu wilayah. Dalam kueri multi-ruang kerja, mungkin tidak menyertakan semua ruang kerja.

Hindari penguraian XML dan JSON penuh saat penguraian string berfungsi

Penguraian penuh objek XML atau JSON mungkin menggunakan sumber daya CPU dan memori yang tinggi. Dalam banyak kasus, ketika hanya satu atau dua parameter yang diperlukan dan objek XML atau JSON sederhana, lebih mudah untuk mengurainya sebagai string. Gunakan operator penguraian atau teknik penguraian teks lainnya. Peningkatan performa akan lebih signifikan karena jumlah rekaman dalam objek XML atau JSON meningkat. Sangat penting ketika jumlah catatan mencapai puluhan juta.

Misalnya, kueri berikut mengembalikan hasil yang sama persis dengan kueri sebelumnya tanpa melakukan penguraian XML penuh. Kueri membuat beberapa asumsi tentang struktur file XML, seperti elemen yang FilePath muncul setelah FileHash dan tidak satu pun dari mereka memiliki atribut:

//even more efficient
SecurityEvent
| where EventID == 8002 //Only this event have FileHash
| where EventData !has "%SYSTEM32" //Early removal of unwanted records
| parse EventData with * "<FilePath>" FilePath "</FilePath>" * "<FileHash>" FileHash "</FileHash>" *
| summarize count() by FileHash, FilePath
| where FileHash != "" // No need to filter out %SYSTEM32 here as it was removed before

Data yang digunakan untuk kueri yang diproses

Faktor penting dalam pemrosesan kueri adalah volume data yang dipindai dan digunakan untuk pemrosesan kueri. Azure Data Explorer menggunakan pengoptimalan agresif yang secara dramatis mengurangi volume data dibandingkan dengan platform data lainnya. Namun, ada faktor penting dalam kueri yang dapat memengaruhi volume data yang digunakan.

Kueri yang memproses lebih dari 2.000 KB data dianggap sebagai kueri yang menggunakan sumber daya yang berlebihan. Kueri yang memproses lebih dari 20.000 KB data dianggap sebagai kueri yang kasar dan mungkin dibatasi.

Di Log Azure Monitor, TimeGenerated kolom digunakan sebagai cara untuk mengindeks data. TimeGenerated Membatasi nilai menjadi sesempit rentang mungkin akan meningkatkan performa kueri. Rentang sempit secara signifikan membatasi jumlah data yang harus diproses.

Hindari penggunaan operator pencarian dan gabungan yang tidak perlu

Faktor lain yang meningkatkan data yang diproses adalah penggunaan sejumlah besar tabel. Skenario ini biasanya terjadi ketika search * dan union * perintah digunakan. Perintah ini memaksa sistem untuk mengevaluasi dan memindai data dari semua tabel di ruang kerja. Dalam beberapa kasus, mungkin ada ratusan tabel di ruang kerja. Cobalah untuk menghindari penggunaan search * atau pencarian apa pun tanpa mencakupnya ke tabel tertentu.

Misalnya, kueri berikut menghasilkan hasil yang sama persis, tetapi yang terakhir adalah yang paling efisien:

// This version scans all tables though only Perf has this kind of data
search "Processor Time" 
| summarize count(), avg(CounterValue)  by Computer
// This version scans all strings in Perf tables – much more efficient
Perf
| search "Processor Time" 
| summarize count(), avg(CounterValue)  by Computer
// This is the most efficient version 
Perf 
| where CounterName == "% Processor Time"  
| summarize count(), avg(CounterValue)  by Computer

Menambahkan filter awal ke kueri

Metode lain untuk mengurangi volume data adalah dengan memiliki kondisi where di awal kueri. Platform Azure Data Explorer menyertakan cache yang memungkinkannya mengetahui partisi mana yang menyertakan data yang relevan untuk kondisi tertentu where . Misalnya, jika kueri berisi where EventID == 4624, maka kueri hanya akan didistribusikan ke simpul yang menangani partisi dengan peristiwa yang cocok.

Contoh kueri berikut menghasilkan hasil yang sama persis, tetapi yang kedua lebih efisien:

//less efficient
SecurityEvent
| summarize LoginSessions = dcount(LogonGuid) by Account
//more efficient
SecurityEvent
| where EventID == 4624 //Logon GUID is relevant only for logon event
| summarize LoginSessions = dcount(LogonGuid) by Account

Hindari beberapa pemindaian data sumber yang sama dengan menggunakan fungsi agregasi kondisional dan fungsi materialisasi

Saat kueri memiliki beberapa subkueri yang digabungkan dengan menggunakan operator gabungan atau gabungan, setiap subkueri memindai seluruh sumber secara terpisah. Kemudian menggabungkan hasilnya. Tindakan ini mengalikan berapa kali data dipindai, yang merupakan faktor penting dalam himpunan data besar.

Teknik untuk menghindari skenario ini adalah dengan menggunakan fungsi agregasi kondisional. Sebagian besar fungsi agregasi yang digunakan dalam operator ringkasan memiliki versi terkondisikan yang dapat Anda gunakan untuk satu operator ringkasan dengan beberapa kondisi.

Misalnya, kueri berikut menunjukkan jumlah peristiwa login dan jumlah peristiwa eksekusi proses untuk setiap akun. Mereka mengembalikan hasil yang sama, tetapi kueri pertama memindai data dua kali. Kueri kedua hanya memindainya sekali:

//Scans the SecurityEvent table twice and perform expensive join
SecurityEvent
| where EventID == 4624 //Login event
| summarize LoginCount = count() by Account
| join 
(
    SecurityEvent
    | where EventID == 4688 //Process execution event
    | summarize ExecutionCount = count(), ExecutedProcesses = make_set(Process) by Account
) on Account
//Scan only once with no join
SecurityEvent
| where EventID == 4624 or EventID == 4688 //early filter
| summarize LoginCount = countif(EventID == 4624), ExecutionCount = countif(EventID == 4688), ExecutedProcesses = make_set_if(Process,EventID == 4688)  by Account

Kasus lain di mana subkueri tidak perlu adalah pra-pemfilteran untuk operator penguraian untuk memastikan bahwa subkueri hanya memproses rekaman yang cocok dengan pola tertentu. Ini tidak perlu karena operator penguraian dan operator serupa lainnya mengembalikan hasil kosong saat pola tidak cocok. Dua kueri berikut mengembalikan hasil yang sama persis, tetapi kueri kedua hanya memindai data sekali. Dalam kueri kedua, setiap perintah penguraian hanya relevan untuk peristiwanya. Operator extend setelah itu menunjukkan cara merujuk ke situasi data kosong:

//Scan SecurityEvent table twice
union(
SecurityEvent
| where EventID == 8002 
| parse EventData with * "<FilePath>" FilePath "</FilePath>" * "<FileHash>" FileHash "</FileHash>" *
| distinct FilePath
),(
SecurityEvent
| where EventID == 4799
| parse EventData with * "CallerProcessName\">" CallerProcessName1 "</Data>" * 
| distinct CallerProcessName1
)
//Single scan of the SecurityEvent table
SecurityEvent
| where EventID == 8002 or EventID == 4799
| parse EventData with * "<FilePath>" FilePath "</FilePath>" * "<FileHash>" FileHash "</FileHash>" * //Relevant only for event 8002
| parse EventData with * "CallerProcessName\">" CallerProcessName1 "</Data>" *  //Relevant only for event 4799
| extend FilePath = iif(isempty(CallerProcessName1),FilePath,"")
| distinct FilePath, CallerProcessName1

Ketika kueri sebelumnya tidak memungkinkan Anda untuk menghindari penggunaan subkueri, teknik lain adalah mengisyaratkan ke mesin kueri bahwa ada satu sumber data yang digunakan di masing-masing dengan menggunakan fungsi materialisasi(). Teknik ini berguna ketika data sumber berasal dari fungsi yang digunakan beberapa kali dalam kueri. Materialize efektif ketika output subkueri jauh lebih kecil dari input. Mesin kueri akan meng-cache dan menggunakan kembali output dalam semua kemunculan.

Mengurangi jumlah kolom yang diambil

Karena Azure Data Explorer adalah penyimpanan data kolom, pengambilan setiap kolom tidak bergantung pada kolom lainnya. Jumlah kolom yang diambil secara langsung memengaruhi volume data keseluruhan. Anda hanya boleh menyertakan kolom dalam output yang diperlukan dengan meringkas hasil atau memproyeksikan kolom tertentu.

Azure Data Explorer memiliki beberapa pengoptimalan untuk mengurangi jumlah kolom yang diambil. Jika menentukan bahwa kolom tidak diperlukan, misalnya, jika tidak dirujuk dalam perintah ringkasan , kolom tidak akan mengambilnya.

Misalnya, kueri kedua mungkin memproses tiga kali lebih banyak data karena perlu mengambil bukan satu kolom tetapi tiga:

//Less columns --> Less data
SecurityEvent
| summarize count() by Computer  
//More columns --> More data
SecurityEvent
| summarize count(), dcount(EventID), avg(Level) by Computer  

Rentang waktu kueri yang diproses

Semua log di Log Azure Monitor dipartisi sesuai dengan TimeGenerated kolom . Jumlah partisi yang diakses terkait langsung dengan rentang waktu. Mengurangi rentang waktu adalah cara paling efisien untuk memastikan eksekusi kueri yang cepat.

Kueri dengan rentang waktu lebih dari 15 hari dianggap sebagai kueri yang menggunakan sumber daya yang berlebihan. Kueri dengan rentang waktu lebih dari 90 hari dianggap sebagai kueri yang melecehkan dan mungkin dibatasi.

Anda dapat mengatur rentang waktu dengan menggunakan pemilih rentang waktu di layar Analitik Log seperti yang dijelaskan dalam Cakupan kueri log dan rentang waktu di Azure Monitor Log Analytics. Metode ini direkomendasikan karena rentang waktu yang dipilih diteruskan ke ujung belakang dengan menggunakan metadata kueri.

Metode alternatif adalah secara eksplisit menyertakan kondisi di mana dalam TimeGenerated kueri. Gunakan metode ini karena memastikan bahwa rentang waktu diperbaiki, bahkan ketika kueri digunakan dari antarmuka yang berbeda.

Pastikan bahwa semua bagian kueri memiliki TimeGenerated filter. Saat kueri memiliki subkueri yang mengambil data dari berbagai tabel atau tabel yang sama, setiap kueri harus menyertakan sendiri kondisi di mana .

Pastikan semua subkueri memiliki filter TimeGenerated

Misalnya, dalam kueri berikut, Perf tabel hanya akan dipindai untuk hari terakhir. Tabel Heartbeat akan dipindai untuk semua riwayatnya, yang mungkin hingga dua tahun:

Perf
| where TimeGenerated > ago(1d)
| summarize avg(CounterValue) by Computer, CounterName
| join kind=leftouter (
    Heartbeat
    //No time span filter in this part of the query
    | summarize IPs = makeset(ComputerIP, 10) by  Computer
) on Computer

Kasus umum saat kesalahan seperti itu terjadi adalah ketika arg_max() digunakan untuk menemukan kejadian terbaru. Contohnya:

Perf
| where TimeGenerated > ago(1d)
| summarize avg(CounterValue) by Computer, CounterName
| join kind=leftouter (
    Heartbeat
    //No time span filter in this part of the query
    | summarize arg_max(TimeGenerated, *), min(TimeGenerated)   
by Computer
) on Computer

Anda dapat dengan mudah memperbaiki situasi ini dengan menambahkan filter waktu di kueri dalam:

Perf
| where TimeGenerated > ago(1d)
| summarize avg(CounterValue) by Computer, CounterName
| join kind=leftouter (
    Heartbeat
    | where TimeGenerated > ago(1d) //filter for this part
    | summarize arg_max(TimeGenerated, *), min(TimeGenerated)   
by Computer
) on Computer

Contoh lain dari kesalahan ini adalah ketika Anda melakukan pemfilteran cakupan waktu tepat setelah persatuan atas beberapa tabel. Saat Anda melakukan union, setiap subkueri harus dilingkup. Anda dapat menggunakan pernyataan let untuk memastikan konsistensi cakupan.

Misalnya, kueri berikut akan memindai semua data dalam Heartbeat tabel dan Perf , bukan hanya hari terakhir:

Heartbeat 
| summarize arg_min(TimeGenerated,*) by Computer
| union (
    Perf 
    | summarize arg_min(TimeGenerated,*) by Computer) 
| where TimeGenerated > ago(1d)
| summarize min(TimeGenerated) by Computer

Untuk memperbaiki kueri:

let MinTime = ago(1d);
Heartbeat 
| where TimeGenerated > MinTime
| summarize arg_min(TimeGenerated,*) by Computer
| union (
    Perf 
    | where TimeGenerated > MinTime
    | summarize arg_min(TimeGenerated,*) by Computer) 
| summarize min(TimeGenerated) by Computer

Batasan pengukuran rentang waktu

Pengukuran selalu lebih besar dari waktu aktual yang ditentukan. Misalnya, jika filter pada kueri adalah 7 hari, sistem mungkin memindai 7,5 atau 8,1 hari. Varians ini karena sistem mempartisi data menjadi potongan ukuran variabel. Untuk memastikan bahwa semua rekaman yang relevan dipindai, sistem memindai seluruh partisi. Proses ini mungkin mencakup beberapa jam dan bahkan lebih dari sehari.

Ada beberapa kasus saat sistem tidak dapat memberikan pengukuran yang akurat terkait rentang waktu. Situasi ini terjadi dalam kebanyakan kasus di mana rentang kueri kurang dari satu hari atau dalam kueri multi-ruang kerja.

Penting

Indikator ini hanya menyajikan data yang diproses dalam kluster langsung. Dalam kueri multi-wilayah, kueri hanya akan mewakili salah satu wilayah. Dalam kueri multi-ruang kerja, mungkin tidak menyertakan semua ruang kerja.

Usia data yang diproses

Azure Data Explorer menggunakan beberapa tingkat penyimpanan: dalam memori, disk SSD lokal, dan Azure Blob yang jauh lebih lambat. Semakin baru data, semakin tinggi kemungkinan data disimpan dalam tingkat yang lebih berkinerja dengan latensi yang lebih kecil, yang mengurangi durasi kueri dan CPU. Selain data itu sendiri, sistem juga memiliki cache untuk metadata. Semakin lama data, semakin kecil kemungkinan metadatanya akan berada dalam cache.

Kueri yang memproses data yang lebih dari 14 hari dianggap sebagai kueri yang mengonsumsi sumber daya berlebihan.

Beberapa kueri memerlukan penggunaan data lama, tetapi ada juga kasus di mana data lama digunakan secara tidak sengaja. Skenario ini terjadi ketika kueri dijalankan tanpa menyediakan rentang waktu dalam metadatanya dan tidak semua referensi tabel menyertakan filter pada TimeGenerated kolom. Dalam kasus ini, sistem akan memindai semua data yang disimpan dalam tabel. Ketika retensi data panjang, retensi data dapat mencakup rentang waktu yang lama. Akibatnya, data yang sama tuanya dengan periode retensi data dipindai.

Kasus seperti itu bisa, misalnya:

  • Tidak mengatur rentang waktu di Log Analytics dengan sub-kueri yang tidak dibatasi. Lihat contoh sebelumnya.
  • Menggunakan API tanpa rentang waktu parameter opsional.
  • Menggunakan klien yang tidak memaksa rentang waktu, misalnya, seperti konektor Power BI.

Lihat contoh dan catatan di bagian sebelumnya karena juga relevan dalam kasus ini.

Jumlah wilayah

Ada situasi di mana satu kueri mungkin dijalankan di berbagai wilayah. Contohnya:

  • Saat beberapa ruang kerja secara eksplisit tercantum dan berada di berbagai wilayah.
  • Saat kueri cakupan sumber daya mengambil data dan data disimpan di beberapa ruang kerja yang berada di berbagai wilayah.

Eksekusi kueri lintas wilayah mengharuskan sistem untuk menserialisasikan dan mentransfer dalam potongan besar ujung belakang data perantara yang biasanya jauh lebih besar dari hasil akhir kueri. Ini juga membatasi kemampuan sistem untuk melakukan pengoptimalan dan heuristik dan menggunakan cache.

Jika tidak ada alasan untuk memindai semua wilayah ini, sesuaikan cakupan sehingga mencakup lebih sedikit wilayah. Jika cakupan sumber daya diminimalkan tetapi banyak wilayah masih digunakan, itu mungkin terjadi karena kesalahan konfigurasi. Misalnya, log audit dan pengaturan diagnostik mungkin dikirim ke ruang kerja yang berbeda di wilayah yang berbeda atau mungkin ada beberapa konfigurasi pengaturan diagnostik.

Kueri yang mencakup lebih dari tiga wilayah dianggap sebagai kueri yang menggunakan sumber daya yang berlebihan. Kueri yang mencakup lebih dari enam wilayah dianggap sebagai kueri yang melecehkan dan mungkin dibatasi.

Penting

Saat kueri dijalankan di beberapa wilayah, pengukuran CPU dan data tidak akan akurat dan hanya akan mewakili pengukuran salah satu wilayah.

Jumlah ruang kerja

Ruang kerja adalah wadah logis yang digunakan untuk memisahkan dan mengelola data log. Back end mengoptimalkan penempatan ruang kerja pada kluster fisik dalam wilayah yang dipilih.

Penggunaan beberapa ruang kerja dapat dihasilkan dari instans saat:

  • Beberapa ruang kerja secara eksplisit tercantum.
  • Kueri cakupan sumber daya mengambil data dan data disimpan di beberapa ruang kerja.

Eksekusi kueri lintas wilayah dan lintas kluster mengharuskan sistem untuk menserialisasikan dan mentransfer dalam potongan besar ujung belakang data perantara yang biasanya jauh lebih besar daripada hasil akhir kueri. Ini juga membatasi kemampuan sistem untuk melakukan pengoptimalan dan heuristik dan menggunakan cache.

Kueri yang mencakup lebih dari lima ruang kerja dianggap sebagai kueri yang menggunakan sumber daya yang berlebihan. Kueri tidak dapat mencakup lebih dari 100 ruang kerja.

Penting

  • Dalam beberapa skenario multi-ruang kerja, pengukuran CPU dan data tidak akan akurat dan akan mewakili pengukuran hanya beberapa ruang kerja.
  • Kueri lintas ruang kerja yang memiliki pengidentifikasi eksplisit: ID ruang kerja, atau ID Sumber Daya Azure ruang kerja, menggunakan lebih sedikit sumber daya dan lebih berkinerja.

Paralelisme

Log Azure Monitor menggunakan kluster besar Azure Data Explorer untuk menjalankan kueri. Kluster ini bervariasi dalam skala besar dan berpotensi mendapatkan hingga puluhan simpul komputasi. Sistem secara otomatis menskalakan kluster sesuai dengan logika dan kapasitas penempatan ruang kerja.

Untuk menjalankan kueri secara efisien, kueri dipartisi dan didistribusikan ke simpul komputasi berdasarkan data yang diperlukan untuk pemrosesannya. Dalam beberapa situasi, sistem tidak dapat melakukan langkah ini secara efisien, yang dapat menyebabkan durasi kueri yang panjang.

Perilaku kueri yang bisa mengurangi paralelisme meliputi:

  • Penggunaan fungsi serialisasi dan jendela, seperti operator serialisasi, next(), prev(), dan fungsi baris. Fungsi rangkaian waktu dan analitik pengguna dapat digunakan dalam beberapa kasus ini. Serialisasi yang tidak efisien mungkin juga terjadi jika operator berikut tidak digunakan di akhir kueri: rentang, pengurutan, urutan, atas, hitter teratas, dan getschema.
  • Penggunaan fungsi agregasi dcount() memaksa sistem untuk memiliki salinan terpusat dari nilai yang berbeda. Ketika skala data tinggi, pertimbangkan untuk dcount menggunakan parameter opsional fungsi untuk mengurangi akurasi.
  • Dalam banyak kasus, operator join menurunkan paralelisme keseluruhan. shuffle join Periksa sebagai alternatif ketika performa bermasalah.
  • Dalam kueri cakupan sumber daya, pemeriksaan kontrol akses berbasis peran (RBAC) Kubernetes pra-eksekusi atau Azure RBAC mungkin berlama-lama dalam situasi di mana ada sejumlah besar penetapan peran Azure. Situasi ini mungkin menyebabkan pemeriksaan lebih lama yang akan mengakibatkan paralelisme yang lebih rendah. Misalnya, kueri mungkin dijalankan pada langganan di mana ada ribuan sumber daya dan setiap sumber daya memiliki banyak penetapan peran pada tingkat sumber daya, bukan pada langganan atau grup sumber daya.
  • Jika kueri memproses potongan kecil data, paralelismenya akan rendah karena sistem tidak akan menyebarkannya di banyak simpul komputasi.

Langkah berikutnya

Dokumentasi referensi untuk Bahasa Kueri Kusto