Benjamin Nevarez adalah konsultan independen yang berbasis di Los Angeles, California yang berspesialisasi dalam penyetelan dan pengoptimalan kueri SQL Server. Dia adalah penulis "SQL Server 2014 Query Tuning &Optimization" dan "Inside the SQL Server Query Optimizer" dan rekan penulis "SQL Server 2012 Internals". Dengan pengalaman lebih dari 20 tahun dalam database relasional, Benjamin juga telah menjadi pembicara di banyak konferensi SQL Server, termasuk PASS Summit, SQL Server Connections, dan SQLBits. Blog Benjamin dapat ditemukan di http://www.benjaminnevarez.com dan dia juga dapat dihubungi melalui email di admin di benjaminnevarez dot com dan di twitter di @BenjaminNevarez.
Pernahkah Anda menemukan regresi rencana setelah pemutakhiran SQL Server dan ingin tahu apa rencana eksekusi sebelumnya? Pernahkah Anda mengalami masalah kinerja kueri karena fakta bahwa kueri tiba-tiba mendapatkan rencana eksekusi baru? Pada PASS Summit terakhir, Conor Cunningham menemukan fitur SQL Server baru, yang dapat membantu dalam memecahkan masalah kinerja yang terkait dengan ini dan perubahan lain dalam rencana eksekusi.
Fitur ini, yang disebut Query Store, dapat membantu Anda dengan masalah kinerja yang terkait dengan perubahan paket dan akan segera tersedia di SQL Azure dan versi SQL Server berikutnya. Meskipun diharapkan akan tersedia di SQL Server Edisi Enterprise, belum diketahui apakah itu akan tersedia di Standar atau edisi lainnya. Untuk memahami manfaat Penyimpanan Kueri, izinkan saya berbicara secara singkat tentang proses pemecahan masalah kueri.
Mengapa Kueri Lambat?
Setelah Anda mendeteksi bahwa masalah kinerja disebabkan oleh kueri yang lambat, langkah selanjutnya adalah mencari tahu alasannya. Jelas tidak setiap masalah terkait dengan perubahan rencana. Mungkin ada beberapa alasan mengapa kueri yang berperforma baik tiba-tiba menjadi lambat. Terkadang ini bisa terkait dengan pemblokiran atau masalah dengan sumber daya sistem lainnya. Sesuatu yang lain mungkin telah berubah tetapi tantangannya mungkin untuk mencari tahu apa. Sering kali kami tidak memiliki dasar tentang penggunaan sumber daya sistem, statistik eksekusi kueri, atau riwayat kinerja. Dan biasanya kita tidak tahu apa rencana lama itu. Mungkin saja beberapa perubahan, misalnya, data, skema, atau parameter kueri, membuat pemroses kueri menghasilkan rencana baru.
Perubahan Rencana
Pada sesi tersebut, Conor menggunakan alat Visualizer Pengoptimal Kueri Database Picasso, meskipun tidak menyebutkan namanya, untuk menunjukkan mengapa paket dalam kueri yang sama berubah, dan menjelaskan fakta bahwa paket yang berbeda dapat dipilih untuk kueri yang sama berdasarkan selektivitas predikatnya. Dia bahkan menyebutkan bahwa tim pengoptimal kueri menggunakan alat ini, yang dikembangkan oleh Institut Sains India. Contoh visualisasi (klik untuk memperbesar):
Visualizer Pengoptimal Kueri Basis Data Picasso
Setiap warna dalam diagram adalah rencana yang berbeda, dan setiap rencana dipilih berdasarkan selektivitas predikat. Fakta penting adalah ketika batas dilintasi dalam grafik dan rencana yang berbeda dipilih, sebagian besar waktu biaya dan kinerja kedua rencana harus serupa, karena selektivitas atau perkiraan jumlah baris hanya berubah sedikit. Ini bisa terjadi misalnya ketika baris baru ditambahkan ke tabel yang memenuhi syarat untuk predikat yang digunakan. Namun, dalam beberapa kasus, sebagian besar karena keterbatasan dalam model biaya pengoptimal kueri yang tidak dapat memodelkan sesuatu dengan benar, paket baru dapat memiliki perbedaan kinerja yang besar dibandingkan dengan yang sebelumnya, menciptakan masalah untuk aplikasi Anda. Omong-omong, rencana yang ditampilkan pada diagram adalah rencana akhir yang dipilih oleh pengoptimal kueri, jangan bingung dengan banyak alternatif yang harus dipertimbangkan oleh pengoptimal untuk memilih hanya satu.
Fakta penting, menurut pendapat saya, yang tidak dibahas secara langsung oleh Conor, adalah perubahan paket karena regresi setelah perubahan pada pembaruan kumulatif (CU), paket layanan, atau peningkatan versi. Perhatian utama yang muncul dalam pikiran dengan perubahan di dalam pengoptimal kueri adalah rencana regresi. Ketakutan akan regresi rencana telah dianggap sebagai hambatan terbesar untuk peningkatan pengoptimal kueri. Regresi adalah masalah yang muncul setelah perbaikan diterapkan ke pengoptimal kueri, dan terkadang disebut sebagai "dua kesalahan atau lebih menjadi benar". Ini bisa terjadi ketika, misalnya, dua estimasi buruk, satu melebih-lebihkan nilai dan yang kedua meremehkannya, membatalkan satu sama lain, untungnya memberikan perkiraan yang baik. Mengoreksi hanya satu dari nilai-nilai ini sekarang dapat menyebabkan estimasi buruk yang dapat berdampak negatif pada pilihan pemilihan rencana, menyebabkan regresi.
Apa Fungsi Toko Kueri?
Conor menyebutkan bahwa Query Store berfungsi dan dapat membantu hal-hal berikut:
- Menyimpan riwayat rencana kueri dalam sistem;
- Tangkap kinerja setiap rencana kueri dari waktu ke waktu;
- Identifikasi kueri yang “semakin lambat akhir-akhir ini”;
- Memungkinkan Anda memaksakan rencana dengan cepat; dan,
- Pastikan ini berfungsi saat server dimulai ulang, peningkatan versi, dan kompilasi ulang kueri.
Jadi fitur ini tidak hanya menyimpan rencana dan informasi kinerja kueri terkait, tetapi juga dapat membantu Anda dengan mudah memaksakan rencana kueri lama, yang dalam banyak kasus dapat memecahkan masalah kinerja.
Cara Menggunakan Toko Kueri
Anda perlu mengaktifkan Toko Kueri dengan menggunakan ALTER DATABASE CURRENT SET QUERY_STORE = ON;
penyataan. Saya mencobanya di langganan SQL Azure saya saat ini, tetapi pernyataan itu mengembalikan kesalahan karena tampaknya fitur tersebut belum tersedia. Saya menghubungi Conor dan dia memberi tahu saya bahwa fitur tersebut akan segera tersedia.
Setelah Penyimpanan Kueri diaktifkan, itu akan mulai mengumpulkan rencana dan data kinerja kueri dan Anda dapat menganalisis data tersebut dengan melihat tabel Penyimpanan Kueri. Saat ini saya dapat melihat tabel tersebut di SQL Azure tetapi, karena saya tidak dapat mengaktifkan Query Store, katalog tidak mengembalikan data.
Anda dapat menganalisis informasi yang dikumpulkan baik secara proaktif untuk memahami perubahan kinerja kueri dalam aplikasi Anda, atau secara surut jika Anda memiliki masalah kinerja. Setelah Anda mengidentifikasi masalah, Anda dapat menggunakan teknik penyetelan kueri tradisional untuk mencoba memperbaiki masalah, atau Anda dapat menggunakan sp_query_store_force_plan
prosedur tersimpan untuk memaksa rencana sebelumnya. Rencana tersebut harus ditangkap di Query Store untuk dipaksakan, yang jelas berarti itu adalah rencana yang valid (setidaknya ketika dikumpulkan; lebih lanjut tentang itu nanti) dan dibuat oleh pengoptimal kueri sebelumnya. Untuk memaksakan rencana, Anda memerlukan plan_id
, tersedia di sys.query_store_plan
katalog. Setelah Anda melihat berbagai metrik yang disimpan, yang sangat mirip dengan yang disimpan misalnya di sys.dm_exec_query_stats
, Anda dapat membuat keputusan untuk mengoptimalkan metrik tertentu, seperti CPU, I/O, dll. Kemudian Anda cukup menggunakan pernyataan seperti ini:
EXEC sys.sp_query_store_force_plan @query_id = 1, @plan_id = 1;
Ini memberitahu SQL Server untuk memaksa rencana 1 pada kueri 1. Secara teknis Anda dapat melakukan hal yang sama menggunakan panduan rencana, tetapi akan lebih rumit dan Anda harus mengumpulkan dan menemukan rencana yang diperlukan secara manual.
Bagaimana Cara Kerja Toko Kueri?
Sebenarnya memaksa rencana menggunakan panduan rencana di latar belakang. Conor menyebutkan bahwa "ketika Anda mengkompilasi kueri, kami secara implisit menambahkan petunjuk USE PLAN dengan fragmen paket XML yang terkait dengan pernyataan itu." Jadi Anda tidak perlu lagi menggunakan plan guide lagi. Juga perlu diingat bahwa, sama seperti menggunakan panduan rencana, tidak dijamin memiliki rencana yang dipaksakan tetapi setidaknya sesuatu yang mirip dengannya. Untuk pengingat tentang cara kerja panduan rencana, lihat artikel ini. Selain itu, Anda harus menyadari bahwa ada beberapa kasus di mana memaksa rencana tidak berhasil, contoh umum adalah ketika skema telah berubah, yaitu jika rencana yang disimpan menggunakan indeks tetapi indeks tidak ada lagi. Dalam hal ini SQL Server tidak dapat memaksa rencana, akan melakukan optimasi normal dan akan merekam fakta bahwa memaksa operasi rencana gagal di sys.query_store_plan
katalog.
Arsitektur
Setiap kali SQL Server mengkompilasi atau mengeksekusi kueri, sebuah pesan dikirim ke Query Store. Ini ditampilkan selanjutnya.
Ikhtisar Alur Kerja Toko Kueri
Informasi kompilasi dan eksekusi disimpan dalam memori terlebih dahulu dan kemudian disimpan ke disk, tergantung pada konfigurasi Query Store (data dikumpulkan menurut INTERVAL_LENGTH_MINUTES
parameter, yang defaultnya adalah satu jam, dan di-flush ke disk sesuai dengan DATA_FLUSH_INTERVAL_SECONDS
parameter). Data juga dapat dipindahkan ke disk jika ada tekanan memori pada sistem. Bagaimanapun, Anda akan dapat mengakses semua data, baik dalam memori dan disk, ketika Anda menjalankan sys.query_store_runtime_stats
katalog.
Katalog
Data yang dikumpulkan disimpan di disk dan disimpan dalam database pengguna tempat Penyimpanan Kueri diaktifkan (dan pengaturan disimpan di sys.database_query_store_options
. Katalog Query Store adalah:
sys.query_store_query_text | Informasi teks kueri |
sys.query_store_query | Teks kueri ditambah paket yang digunakan memengaruhi opsi SET |
sys.query_store_plan | Rencana eksekusi, termasuk riwayat |
sys.query_store_runtime_stats | Statistik waktu proses kueri |
sys.query_store_runtime_stats_interval | Waktu mulai dan berakhir untuk interval |
sys.query_context_settings | Informasi setelan konteks kueri |
tampilan Toko Kueri
Statistik runtime menangkap banyak metrik, termasuk rata-rata, terakhir, min, maks, dan standar deviasi. Berikut adalah kumpulan kolom lengkap untuk sys.query_store_runtime_stats
:
runtime_stats_id | plan_id | runtime_stats_interval_id | ||
execution_type | execution_type_desc | first_execution_time | last_execution_time | count_executions |
avg_duration | last_duration | min_duration | max_duration | stdev_duration |
avg_cpu_time | last_cpu_time | min_cpu_time | max_cpu_time | stdev_cpu_time |
avg_logical_io_reads | last_logical_io_reads | min_logical_io_reads | max_logical_io_reads | stdev_logical_io_reads |
avg_logical_io_writes | last_logical_io_writes | min_logical_io_writes | max_logical_io_writes | stdev_logical_io_writes |
avg_physical_io_reads | last_physical_io_reads | min_physical_io_reads | max_physical_io_reads | stdev_physical_io_reads |
avg_clr_time | last_clr_time | min_clr_time | max_clr_time | stdev_clr_time |
avg_dop | last_dop | min_dop | max_dop | stdev_dop |
avg_query_max_used_memory | last_query_max_used_memory | min_query_max_used_memory | max_query_max_used_memory | stdev_query_max_used_memory |
avg_rowcount | last_rowcount | min_rowcount | max_rowcount | stdev_rowcount |
Kolom di sys.query_store_runtime_stats
Data ini hanya diambil saat eksekusi kueri berakhir. Penyimpanan Kueri juga mempertimbangkan SET
. kueri opsi, yang dapat memengaruhi pilihan rencana eksekusi, karena memengaruhi hal-hal seperti hasil evaluasi ekspresi konstan selama proses pengoptimalan. Saya membahas topik ini di posting sebelumnya.
Kesimpulan
Ini pasti akan menjadi fitur hebat dan sesuatu yang ingin saya coba sesegera mungkin (omong-omong, demo Conor menunjukkan "SQL Server 15 CTP1" tetapi bit itu tidak tersedia untuk umum). Penyimpanan Kueri dapat berguna untuk pemutakhiran yang dapat berupa CU, paket layanan, atau versi SQL Server, karena Anda dapat menganalisis informasi yang dikumpulkan oleh Penyimpanan Kueri sebelum dan sesudah untuk melihat apakah ada kueri yang mengalami kemunduran. (Dan jika fitur tersebut tersedia dalam edisi yang lebih rendah, Anda bahkan dapat melakukannya dalam skenario peningkatan SKU.) Mengetahui hal ini dapat membantu Anda untuk mengambil beberapa tindakan spesifik tergantung pada masalahnya, dan salah satu solusi tersebut dapat memaksa rencana sebelumnya seperti yang dijelaskan sebelumnya.