10 Şubat 2014 Pazartesi

Inline TVF mı yoksa Multi Statement TVF mı? Mümkünse Inline lütfen!

Merhaba!


Size kısaca Inline (ITVF) ve Multi Statement Table Valued Function (MSTVF)'ların kullanımı ve farkından bahsetmek istiyorum.

Bugün bir sunucumuzda performans kontrolü yaparken bir sorgunun çok masraf oluşturduğunu gördüm. Sorguyu incelerken içerisinde bir Table Valued Function (TVF)'ın kullanıldığını fark ettim. Bu TVF'ı kontrol ederken, sadece bir sorgudan oluşan bir işlem olmasına rağmen MSTVF olarak aşağıdaki gibi yazıldığını gördüm (kritik bilgileri değiştirdim)

MSTVF
ALTER FUNCTION [dbo].[fTVFsorgu] (@degisken1 varchar(50))
RETURNS @TVF TABLE
(
Adres varchar(250)
,Belediye varchar(50)
,Mahalle varchar(50)
,Sokak varchar(50)
,islem_kodu int
)
AS
BEGIN
   INSERT @TVF
Select 
Adres
,Belediye
,Mahalle
,Sokak
,islem_kodu
FROM dbo.tablo_adi
WHERE AdSoyad=@degisken1
RETURN
END

Görüldüğü üzere bu TVF sadece bir sorgudan oluşuyor. 

Bazılarınızın "Peki bu tür sorguları ITVF olarak yazmakta fayda var? Fark nedir ki?" dediğinizi tahmin edebiliyorum. Şöyle ki, MSTVF'lardaki Table değişkenlerinin içinde kaç tane kayıt olursa olsun, SQL Server MSTVF'lardaki Table değişkenlerinin içinde sadece 1 tane kayıt olduğunu varsayar. MSTVF'ler SQL Server Query Optimizer için de bir karakutudur. Hal böyle olunca, uygun Index'lerden ve Statistic'lerden faydalanılamaz. Yani sorgu için Query Optimizer gerekli iyileştirme işlemlerini yapamaz.

Eğer TVF'ınınız içerisinde özellikle sadece bir Statement varsa çoğu zaman bunu ITVF'a çevirmenizde büyük fayda var. Eğer birden fazla Statement varsa da o zaman mümkünse bu Statement'ları birleştirip bir tane Statement şeklinde düzenleyip bu şekilde ITVF kullanmanız ve bu şekilde test etmeniz iyi olur.


ITVF
CREATE FUNCTION [dbo].[fTVFsorgu] (@degisken1 varchar(50))
RETURNS TABLE
AS
RETURN
Select 
Adres
,Belediye
,Mahalle
,Sokak
,islem_kodu
FROM dbo.tablo_adi
WHERE AdSoyad=@degisken1

Bu arada, eğer MSTVF ile ITVF'ın Execution Plan'larını doğrudan SQL Server Management Studio ile karşılaştıracak olursanız sizi yanıltabilecek bir sonuç ile karşılaşmanız kaçınılmaz. Çünkü burada MSTVF ile ilgili tablo üstünde yapılan IO işlemi dahil edilmiyor, fakat ITVF ile yapılan IO işlemleri dahil ediliyor. İlgili ekran görüntüsünü aşağıda görebilirsiniz:



Gördüğünüz gibi ITVF kullandığımızda artık bir karakutuyla (MSTVF) uğraşmamış oluyoruz ve tüm planı görebiliyoruz. Bu sayede en çok masraf oluşturan kalemleri de belirleyip gerekli aksiyonları alabiliyoruz. Bu örnekte ben Index'i Covered Index yapmadan önce aşağıdaki ITVF ilgili Index'teki alan için SEEK yaparken, diğer alanlar için Lookup yapıyordu ve bu da büyük bir IO masrafı oluşturuyordu. Fakat Index'i Covered Index yaptıktan sonra artık tamamen SEEK yapmaya başladı ve Query Optimizer da ITVF'daki sorguyu işleyebildiği için hemen bu Index'ten faydalandı ve performans çok arttı. Bu iyileşmenin sonucu için aşağıdaki ekran görüntüsüne bakabilirsiniz. 



Hem Index'in Covered Index'e çevrilmesiyle, hem de bu Function'ın MSTVF'dan ITVF'a çevrilerek Query Optimizer'ın bu sorguyu değerlendirip bu Index'ten faydalanılmasını sağlanmasıyla nasıl bir iyileşme yaşandığını görüyorsunuz. Uygun Index olmasına rağmen MSTVF bu Index'ten faydalanamıyor.

Kolay gelsin,
Ekrem Önsoy






Hiç yorum yok: