Latar Belakang
Saya memiliki kueri yang berjalan terhadap SQL Server 2008 R2 yang bergabung dan / atau bergabung-kiri sekitar 12 "tabel" berbeda. Basis datanya cukup besar dengan banyak tabel lebih dari 50 juta baris dan sekitar 300 tabel berbeda. Ini untuk perusahaan besar yang memiliki 10 gudang di seluruh negeri. Semua gudang membaca dan menulis ke database. Jadi itu cukup besar dan sangat sibuk.
Kueri yang bermasalah dengan tampilannya adalah seperti ini:
select t1.something, t2.something, etc.
from Table1 t1
inner join Table2 t2 on t1.id = t2.t1id
left outer join (select * from table 3) t3 on t3.t1id = t1.t1id
[etc]...
where t1.something = 123
Perhatikan bahwa salah satu gabungan adalah pada sub-kueri yang tidak berkorelasi.
Masalahnya adalah bahwa mulai pagi ini, tanpa perubahan apa pun (yang saya atau siapa pun di tim saya ketahui) ke sistem, permintaan yang biasanya memakan waktu sekitar 2 menit untuk berjalan, mulai mengambil satu setengah jam untuk berjalan - ketika itu berlari sama sekali. Sisa dari database bersenandung dengan baik. Saya telah mengeluarkan query ini dari sproc yang biasanya dijalankan dan saya menjalankannya dalam SSMS dengan variabel parameter hard-coded dengan kelambatan yang sama.
Anehnya adalah ketika saya mengambil sub-kueri yang tidak berkorelasi dan membuangnya ke tabel temp, dan kemudian menggunakannya sebagai pengganti sub-kueri, kueri berjalan dengan baik. Juga (dan ini yang paling aneh bagi saya) jika saya menambahkan potongan kode ini ke akhir kueri, kueri berjalan hebat:
and t.name like '%'
Saya telah menyimpulkan (mungkin salah) dari percobaan kecil ini bahwa alasan untuk perlambatan adalah karena bagaimana rencana eksekusi cached SQL diatur - ketika kueri sedikit berbeda, ia harus membuat rencana eksekusi baru.
Pertanyaan saya adalah ini: Ketika kueri yang digunakan untuk berlari cepat tiba-tiba mulai berjalan lambat di tengah malam dan tidak ada yang lain yang terpengaruh kecuali untuk permintaan yang satu ini, bagaimana cara saya memecahkan masalah dan bagaimana saya mencegahnya terjadi di masa depan ? Bagaimana saya tahu apa yang SQL lakukan secara internal untuk membuatnya sangat lambat (jika permintaan buruk berjalan, saya bisa mendapatkan rencana pelaksanaannya tetapi itu tidak akan berjalan - mungkin rencana eksekusi yang diharapkan akan memberi saya sesuatu?)? Jika masalah ini adalah dengan rencana eksekusi, bagaimana saya menjaga SQL dari berpikir bahwa rencana eksekusi yang benar-benar jelek adalah ide yang bagus?
Juga, ini bukan masalah dengan sniffing parameter. Saya telah melihat itu sebelumnya, dan ini bukan itu, karena bahkan ketika saya hard-code varaibles di SSMS, saya masih mendapatkan kinerja yang lambat.