Saya akan mengatakan dari awal bahwa pertanyaan saya / masalah terlihat mirip dengan yang sebelumnya ini , tetapi karena saya tidak yakin apakah penyebab atau info awal adalah sama, saya memutuskan untuk mengirim pertanyaan saya dengan lebih jelas.
Masalah yang dihadapi:
- pada jam yang aneh (menjelang akhir hari kerja) sebuah instance produksi mulai berperilaku tidak menentu:
- CPU tinggi untuk contoh (dari baseline ~ 30% itu menjadi sekitar dua kali lipat dan masih tumbuh)
- peningkatan jumlah transaksi / detik (meskipun aplikasi memuat tidak melihat adanya perubahan)
- peningkatan jumlah sesi siaga
- peristiwa pemblokiran aneh antara sesi yang tidak pernah menampilkan perilaku ini (bahkan membaca sesi tanpa komitmen menyebabkan pemblokiran)
- menunggu top untuk interval adalah non latch halaman di tempat 1, dengan kunci mengambil tempat 2
Investigasi awal:
- menggunakan sp_whoIsActive kami melihat bahwa permintaan yang dijalankan oleh alat pemantauan kami memutuskan untuk berjalan sangat lambat dan mengambil banyak CPU, sesuatu yang tidak terjadi sebelumnya;
- tingkat isolasi dibaca tidak terikat;
- kami melihat paket yang kami lihat angka aneh: StatementEstRows = "3,86846e + 010" dengan sekitar 150 TB data yang diperkirakan akan dikembalikan
- kami menduga fitur monitor permintaan dari alat pemantauan adalah penyebabnya, jadi kami menonaktifkan fitur tersebut (kami juga membuka tiket dengan penyedia kami untuk memeriksa apakah mereka mengetahui ada masalah)
- dari peristiwa pertama itu, terjadi beberapa kali lagi, dengan setiap kali kita membunuh sesi, semuanya kembali normal;
- kami menyadari bahwa kueri sangat mirip dengan salah satu kueri yang digunakan oleh MS di BOL untuk pemantauan Toko Kueri - Kueri yang baru-baru ini mengalami penurunan kinerja (membandingkan berbagai titik waktu)
- kami menjalankan kueri yang sama secara manual dan melihat perilaku yang sama (CPU yang digunakan semakin meningkat, meningkatkan latch menunggu, kunci tak terduga .. dll)
Permintaan bersalah:
Select qt.query_sql_text,
q.query_id,
qt.query_text_id,
rs1.runtime_stats_id AS runtime_stats_id_1,
interval_1 = DateAdd(minute, -(DateDiff(minute, getdate(), getutcdate())), rsi1.start_time),
p1.plan_id AS plan_1,
rs1.avg_duration AS avg_duration_1,
rs2.avg_duration AS avg_duration_2,
p2.plan_id AS plan_2,
interval_2 = DateAdd(minute, -(DateDiff(minute, getdate(), getutcdate())), rsi2.start_time),
rs2.runtime_stats_id AS runtime_stats_id_2
From sys.query_store_query_text AS qt
Inner Join sys.query_store_query AS q
ON qt.query_text_id = q.query_text_id
Inner Join sys.query_store_plan AS p1
ON q.query_id = p1.query_id
Inner Join sys.query_store_runtime_stats AS rs1
ON p1.plan_id = rs1.plan_id
Inner Join sys.query_store_runtime_stats_interval AS rsi1
ON rsi1.runtime_stats_interval_id = rs1.runtime_stats_interval_id
Inner Join sys.query_store_plan AS p2
ON q.query_id = p2.query_id
Inner Join sys.query_store_runtime_stats AS rs2
ON p2.plan_id = rs2.plan_id
Inner Join sys.query_store_runtime_stats_interval AS rsi2
ON rsi2.runtime_stats_interval_id = rs2.runtime_stats_interval_id
Where rsi1.start_time > DATEADD(hour, -48, GETUTCDATE())
AND rsi2.start_time > rsi1.start_time
AND p1.plan_id <> p2.plan_id
AND rs2.avg_duration > rs1.avg_duration * 2
Order By q.query_id, rsi1.start_time, rsi2.start_time
Pengaturan dan info:
- SQL Server 2016 SP1 CU4 Enterprise pada kluster Windows Server 2012R2
- Query Store diaktifkan dan dikonfigurasi sebagai default (tidak ada pengaturan berubah)
- database yang diimpor dari contoh SQL 2005 (dan masih pada tingkat kompatibilitas 100)
Pengamatan empiris:
- karena statistik yang sangat aneh, kami mengambil semua * plan_persist ** objek yang digunakan dalam rencana taksiran buruk (belum ada rencana sebenarnya, menyebabkan kueri tidak pernah selesai) dan memeriksa statistik, beberapa indeks yang digunakan dalam rencana tidak memiliki statistik (DBCC SHOWSTATISTICS tidak mengembalikan apa pun, pilih dari sys.stats menunjukkan fungsi NULL stats_date () untuk beberapa indeks
Solusi cepat dan kotor:
- secara manual membuat statistik yang hilang pada objek sistem yang terkait dengan Query Store atau
- memaksa kueri untuk berjalan menggunakan CE (traceflag) baru - yang juga akan membuat / memperbarui statistik yang diperlukan atau
- ubah tingkat kompatibilitas basis data menjadi 130 (sehingga secara default akan menggunakan CE baru)
Jadi, pertanyaan saya yang sebenarnya adalah:
Mengapa kueri di Query Store menyebabkan masalah kinerja di seluruh instance? Apakah kita berada di wilayah bug dengan Query Store?
PS: Saya akan mengunggah beberapa file (layar cetak, statistik IO, dan paket) dalam waktu singkat.
File ditambahkan di Dropbox .
Rencana 1 - rencana perkiraan awal yang aneh dalam produksi
Rencana 2 - rencana aktual, CE lama, dalam pengujian env (perilaku yang sama, statistik aneh yang sama)
Rencana 3 - rencana aktual, CE baru, dalam pengujian env
Jawaban:
Seperti yang saya katakan dalam jawaban, tes empiris menunjukkan bahwa ada indeks pada objek sistem sys.plan_persisted * tanpa (tidak ada) statistik yang dibuat atas mereka. Saya menduga itu karena database dimigrasikan dari contoh SQL 2005, dan disimpan untuk sementara waktu pada tingkat kompatibilitas 100, sehingga CE baru tidak bisa digunakan.
Pemeriksaan jumlah baris:
Ini menunjukkan bahwa perkiraan awal salah. Selesai dengan koneksi DAC, jika tidak, tabel tidak tersedia untuk kueri.
Statistik memeriksa:
Ini menunjukkan bahwa beberapa indeks memiliki statistik kosong (hilang, tidak ada, nol).
Perbaikan awal:
Jenis ini memperbaiki statistik dan membuat kueri selesai dalam 10-12 detik.
Perbaikan kedua :
(diverifikasi hanya pada lingkungan pengujian) dan kemungkinan besar yang tepat, karena menunjukkan statistik terbaik untuk kueri, adalah mengubah tingkat kompatibilitas database menjadi 130. Hasil akhirnya adalah bahwa kueri berakhir sekitar 10-12 detik dengan statistik angka normal (baris 10rb).
Perbaikan tingkat menengah :
Beberapa bantuan terkait tentang statistik pada tabel tersembunyi sistem.
sumber
Masalah mendasar, yang terlihat jika Anda membuka rencana aktual dalam SSMS dan melihat penggunaan CPU (atau memeriksa XML), adalah node 32, sebuah TVF. Pelakunya dalam permintaan Query Store lambat adalah akses berulang TVF dalam memori .
Tidak peduli berapa banyak baris yang dikembalikan dari TVF ini, hanya berapa kali mereka diakses. Cara mengatasinya adalah apa pun yang dapat Anda lakukan untuk mendorong rencana Anda agar tidak membacanya berulang kali.
Berdasarkan pada debugging terbatas saya (baik dalam keterampilan dan waktu yang dihabiskan), hipotesis saya adalah bahwa keseluruhan memori yang ditetapkan untuk komponen dalam-memori tertentu dari data Query Store dipindai dengan setiap eksekusi TVF. Saya belum dapat memengaruhi alokasi memori ini dengan
sp_query_store_flush_db
atauDBCC FREESYSTEMCACHE
.Solusi yang berhasil sejauh ini termasuk panduan rencana, mengisyaratkan (
OPTION(HASH JOIN, LOOP JOIN)
telah bekerja cukup baik untuk saya sejauh ini), dan menjalankan kueri Toko Kueri pada simpul read-only dari AG.sumber