Bu sorunu uzun zaman önce yaşadım, bana uygun bir çözüm buldum ve unuttum.
Ama şimdi SO ile ilgili bir soru var, bu yüzden bu sorunu gündeme getirmeye hazırım.
Birkaç tabloyu çok basit bir şekilde birleştiren bir görünüm var (siparişler + sipariş satırları).
where
Madde olmadan sorgulandığında , görünüm birkaç milyon satır döndürür.
Ancak, hiç kimse bunu böyle demez. Genel sorgu
select * from that_nasty_view where order_number = 123456;
Bu, 5 metreden yaklaşık 10 kayıt döndürür.
Önemli bir şey: görünüm rank()
, görünümün her zaman sorgulandığı alanla tam olarak bölümlenmiş bir pencere işlevi içerir :
rank() over (partition by order_number order by detail_line_number)
Şimdi, bu görünüm tam olarak yukarıda gösterildiği gibi sorgu dizesindeki değişmez parametrelerle sorgulanırsa, satırları anında döndürür. Uygulama planı gayet iyi:
- Endeksleri her iki tabloda da indeksleri kullanarak arayın
order_number
(10 satır döndürür). - Geri dönen küçük sonuç üzerinden pencereleri hesaplamak.
- Seçme.
Ancak, görünüm parametreli bir şekilde çağrıldığında işler kötü olur:
Index scan
endeksleri yok sayarak tüm tablolarda. 5m satır döndürür.- Büyük katılım.
- Pencereleri tüm
partition
s (yaklaşık 500k pencereler) üzerinden hesaplama . Filter
5 metreden 10 sıra almak.- seçmek
Bu, parametrelerin dahil olduğu tüm durumlarda olur. SSMS olabilir:
declare @order_number int = 123456;
select * from that_nasty_view where order_number = @order_number;
Excel gibi bir ODBC istemcisi olabilir:
select * from that_nasty_view where order_number = ?
Veya sql birleşimini değil, parametreleri kullanan başka herhangi bir istemci olabilir.
Pencere işlevi görünümden kaldırılırsa, parametrelerle sorgulanıp sorgulanmamasına bakılmaksızın mükemmel bir şekilde hızlı çalışır.
Geçici çözümüm, rahatsız edici işlevi kaldırmak ve daha sonraki bir aşamada yeniden uygulamaktı.
Ama ne verir? SQL Server 2008'in pencere işlevlerini işleme biçiminde gerçekten bir hata mı var?
order_number
birincil anahtar değildir. Her int not null
iki tabloda da kümelenmemiş dizin ile.
OPTION (RECOMPILE)
yardımcı olur mu?