Bagaimana saya bisa menghapus rencana eksekusi yang buruk dari Azure SQL Database?

12

DBCC FREEPROCCACHEtidak bekerja di Azure SQL DB. Bagaimana lagi saya bisa memaksakan rencana untuk menendang keluar dari cache dengan cara yang tidak akan merusak sistem produksi (yaitu saya tidak bisa begitu saja mengubah tabel mau tak mau)? Ini khusus untuk SQL yang dibuat oleh Entity Framework, jadi ini bukan procs tersimpan yang dikelola sendiri - ini SQL dinamis yang efektif.

(Sumber adalah indeks buruk -> statistik buruk, dll. Itu semua sudah diperbaiki, tetapi rencana yang buruk tidak akan hilang.)

UPDATE: Saya memilih solusi @ mrdenny ketika dia sampai di sana dulu. Namun, saya berhasil menggunakan skrip @Aaron Bertrand untuk melakukan pekerjaan itu. Terima kasih untuk semua orang atas bantuannya !!

Jaxidian
sumber
Bisakah Anda melakukan sp_recompile di Azure?
mrdenny
Iya. Apa tepatnya yang akan saya jalankan? Kami tidak memiliki procs yang disimpan. Ini adalah SQL dinamis yang dijalankan sp_executesql.
Jaxidian
2
Anda bisa menjalankannya di atas meja sendiri dan itu akan menggelontorkan rencana yang menggunakan tabel itu. (Jika ini berhasil, saya akan menjawabnya.)
mrdenny
1
Saya baru saja mencoba ini di atas meja dan tampaknya mengunci tabel dalam transaksi saat memproses. Saya mencobanya di atas meja 10 kolom dengan hanya 24 catatan dan butuh lebih dari satu menit untuk menyelesaikannya. Selama waktu ini, saya tidak dapat menanyakan tabel. Saya tidak dapat menjalankan sesuatu seperti itu di meja nyata kami di Produksi!
Jaxidian
1
Sial, itu mengecewakan. Sepertinya Anda harus melakukan perubahan skema seperti menambahkan kolom yang dapat dibatalkan, lalu letakkan. Itu akan menghapus cache juga dan harus quick'ish. Pengujian akan memberi tahu pasti.
mrdenny

Jawaban:

12

Azure SQL sekarang langsung mendukung ini

Azure SQL Database secara langsung mendukung pembersihan cache proc dari database pengguna saat ini tanpa peretasan:

ALTER DATABASE SCOPED CONFIGURATION CLEAR PROCEDURE_CACHE;

informasi tambahan

Script berikut (oleh Shannon Gowen ) dapat digunakan untuk menonton proses langkah-demi-langkah:

-- run this script against a user database, not master
-- count number of plans currently in cache
select count(*) from sys.dm_exec_cached_plans;

-- Executing this statement will clear the procedure cache in the current database, which means that all queries will have to recompile.
ALTER DATABASE SCOPED CONFIGURATION CLEAR PROCEDURE_CACHE;

-- count number of plans in cache now, after they were cleared from cache
select count(*) from sys.dm_exec_cached_plans;

-- list available plans
select * from sys.dm_exec_cached_plans;
Todd Menier
sumber
Saya belum mencoba ini tetapi jika ini sebenarnya fungsional, maka ini mungkin jawaban "terbaik" pada awal 2017. Terima kasih untuk ini - saya tidak tahu ini ada di sana! :-)
Jaxidian
Saya sudah mencoba ini (pada DB Premium) dan berhasil.
Remi Lemarchand
Saya telah menandai ini sebagai "Jawaban yang Diterima" yang diperbarui, tetapi saya belum mengujinya sendiri. Saya mendasarkan ini langsung pada umpan balik Todd dan Remi. Terima kasih semuanya!
Jaxidian
Hanya untuk meninjau kembali, saya telah menggunakan ini dan itu bekerja dengan baik untuk saya! Saya menambahkan beberapa skrip tambahan untuk jawaban Todd di sini untuk memperkaya tetapi tulisannya menyentuh kepala.
Jaxidian
Ini sepertinya tidak berfungsi untuk saya - hanya dijalankan tetapi daftarnya masih penuh - Saya menggunakan SQL Azure - apa yang bisa salah?
Dirk Boer
12

Tidak ada cara eksplisit untuk melakukan ini hari ini, tapi itu bukan skenario permanen (perintah DBCC masih belum didukung, tetapi baca di Query Store ). Bahkan ketika perubahan skema diterima, itu mungkin bukan yang Anda inginkan, karena itu akan membatalkan semua rencana yang terkait dengan objek yang mendasarinya, bukan hanya yang buruk.

Tidak mencari kredit untuk ini, tetapi membangun SQL dinamis untuk melakukan operasi yang sama terhadap beberapa tabel cukup mudah:

DECLARE @sql NVARCHAR(MAX) = N'';

SELECT @sql += N'ALTER TABLE '
  + QUOTENAME(SCHEMA_NAME([schema_id])) 
  + '.' + QUOTENAME(name) + ' ADD fake_column INT NULL;
  ALTER TABLE ' 
  + QUOTENAME(SCHEMA_NAME([schema_id]))
  + '.' + QUOTENAME(name) + ' DROP COLUMN fake_column;'
FROM sys.tables
--WHERE name IN, LIKE, etc.

PRINT @sql;

-- if the command > 8K, you can see the second chunk e.g.

PRINT SUBSTRING(@sql, 8001, 8000);

--EXEC sys.sp_executesql @sql;

(Saya menulis tip tentang masalah "panjang SQL dinamis" ini ...)

Aaron Bertrand
sumber
Dalam kasus saya, menghapus semuanya jauh lebih baik daripada meninggalkan yang buruk di sana. Terimakasih atas peringatannya. Saya tahu Anda tidak dapat memberi tahu saya fitur tetapi bisakah Anda memberi tahu saya ketika Anda mungkin tidak lagi dibatasi untuk membicarakan hal-hal yang tidak dapat Anda bicarakan? ;-)
Jaxidian
Itu juga diklasifikasikan, maaf. :-)
Aaron Bertrand
Tidak yakin apa yang Anda maksud dengan tautan. Yang saya maksudkan adalah bahwa nvarchar(max)variabel Anda mencapai batas setelah 4000 karakter, 8000 karakter jika saya mengubahnya varchar(max). Menjalankan skrip yang tepat. Kami memiliki ~ 450 tabel, jadi kami dapat dengan mudah (~ 30/60 tabel di). varchar(max)sintaks yang valid, hanya identik dengan varchar(8000), dan nvarchar(max)identik dengan nvarchar(4000).
Jaxidian
3
Ya, ketika Anda PRINTperintah, itu hanya menampilkan 8000 byte. Itu adalah batasan PRINTperintah, bukan Azure. Jika Anda menjalankan perintah itu akan berfungsi bahkan jika Anda tidak dapat memeriksa semuanya secara visual.
Aaron Bertrand
... doh, maaf, saya pikir kamu benar! Terima kasih telah mengoreksi saya! Itulah yang terjadi ketika istri Anda mengharapkan Anda pergi 25 menit yang lalu ... ;-) Skrip ini berfungsi dengan baik untuk saya!
Jaxidian
6

Tambahkan kolom nullable ke tabel lalu jatuhkan kolom. Itu akan memaksa SQL untuk membersihkan cache untuk objek itu.

Sedangkan untuk melakukan semua tabel, kursor harus melakukan trik. Cukup gunakan nama kolom yang tidak akan pernah ada di tabel apa pun seperti 'zzzzzz_go_away' atau sesuatu.

mrdenny
sumber
4

Database SQL Azure saat ini tidak mendukung DBCC FREEPROCCACHE, jadi Anda tidak bisa menghapus rencana eksekusi dari cache secara manual. Namun, jika Anda membuat perubahan pada tabel atau tampilan yang dirujuk oleh kueri ( ALTER TABLE/ ALTER VIEW) paket tersebut akan dihapus dari cache. ( Referensi .)

Kin Shah
sumber
Saya sudah tahu semua yang Anda posting di sini. Ini bukan prosedur tersimpan atau tampilan, jadi saya tidak bisa memodifikasi salah satunya. Bagaimana saya bisa memodifikasi tabel saya dengan cara yang tidak signifikan, saat sedang dimuat dan tanpa menyebabkan downtime atau mengunci tabel, untuk memicu ini?
Jaxidian
1
Anda bisa menambahkan kolom dummy lalu menjatuhkannya. Ini akan menghapus paket dari cache. Seberapa besar meja?
Kin Shah
Itu akhirnya menjadi solusi, seperti yang direkomendasikan oleh @rdenny. Terima kasih untuk bantuannya!! :-)
Jaxidian
1
Terima kasih ... Hanya beberapa detik dalam waktu singkat .. Menjawab beberapa posting lain di stackexchange ...
Kin Shah
1

Untuk menghapus semua rencana eksekusi, gunakan ini:

    SET NOCOUNT ON

DECLARE @lcl_name VARCHAR(100)
DECLARE @addcolumnSql nVARCHAR(MAX)
DECLARE @dropcolumnSql nVARCHAR(MAX)

DECLARE cur_name CURSOR FOR
SELECT name
FROM sysobjects
WHERE type = 'U'
OPEN cur_name
FETCH NEXT FROM cur_name INTO @lcl_name
WHILE @@Fetch_status = 0
BEGIN
set @addcolumnSql = 'alter table [' + @lcl_name + '] add temp_col_to_clear_exec_plan bit'
EXEcute sp_executesql @addcolumnSql
print @addcolumnSql
set @dropcolumnSql = 'alter table [' + @lcl_name + '] drop column temp_col_to_clear_exec_plan'
EXEcute sp_executesql @dropcolumnSql
print @dropcolumnSql
--  EXEC (@lcl_name )
FETCH NEXT FROM cur_name INTO @lcl_name
END
CLOSE cur_name
DEALLOCATE cur_name
SET NOCOUNT OFF

Jika Anda mengubah tabel atau tampilan referensi itu, rencana eksekusi dihapus.

Sedikit lebih dijelaskan di sini http://christianarg.wordpress.com/2013/08/22/remove-execution-plans-dari-prosedur-cache-in-sql-azure/

Kristen
sumber