-
- Üyelik Tarihi
- 24 Mar 2017
-
- Mesajlar
- 4,578
-
- MFC Puanı
- 1,437
SQL Server'da yazılan sorguların performanslı bir şekilde çalışmalarını sağlamak için kullanılan çeşitli seçenekler bulunmaktadır. Bu seçenekleri kullanarak daha optimize sorgular yazılabilmekte ve Execution Plan'lar incelenerek yazılan sorguların karşılaştırmaları yapılabilmektedir. Bu yazımızda bu seçeneklerden biri olan Fast N seçeneğini ele alacağız.
SQL Serverda Execution Plan'a müdahale ederken kullanılan faydalı kullanımlardan biri de Fast N seçeneğidir. Sıkça karıştırılan bu operatörü kullanarak, SQL Serverın sorgu sonucunda gösterilecek olan sonuç kümesinin içinde N (N pozitif bir sayı) tane kaydı en hızlı getirecek şekilde Execution Planı optimize etmesini sağlayabiliriz. Fakat dikkat edilmesi gereken nokta burada verilen N pozitif bir sayı olmakla beraber gösterilecek kayıt sayısı ile alakalı değildir. Şöyle ki sorgumuzun sonucunda 1000 tane kayıt döndüğü durumda bu 1000 kaydın ilk 10 tanesinin olabilecek en hızlı bir şekilde ekrana getirilmesi ve kalan 990 tanesinin de ilk 10 tane hızlı bir şekilde gösterildikten sonra normal bir şekilde ekranda gösterilmesi isteniyorsa SQL Server'da bulunan Fast N seçeneği kullanılarak bu işlem çok daha performanslı bir şekilde gerçekleştirilebilmektedir. Ancak bu operatör çoğu zaman kayıt kümesinin N tane kayıt ile sınırlandırılacağı olarak düşünülmektedir. Bu yanılgıya düşülmemeli ve buna göre sorgular yazılmalıdır.
Şimdi Fast N operatörünün nasıl kullanıldığını bir örnek üzerinde görelim. İlk sorgumuzda Fast N operatörünü kullanmadan Execution Planımızı inceleyelim daha sonra aynı sorgumuzu Fast N operatörünü kullanarak SQL Server'ın kullanacağı Execution Planı inceleyelim ve karşılaştıralım.
Yukarıdaki sorgumuzda Production.Product tablosu ile Sales.SalesOrderDetail tablosunu Inner Join ile birleştirdik. Şimdi Execution Planımızı inceleyelim.
Yukarıdaki resimde sorgumuzun Execution planını incelediğimizde Sales.SalesOrderDetail tablosundaki veriler Clustered Index Scan işlemi ile okunup Compute Scalar operatörü ile tabloda bulunan Computed Column (Hesaplanmış Sütun) değeri hesaplanarak elde edilen sonuç kümesi ile Production.Product tablosu üzerinde yapılan Clustered Index Scan işleminin sonucu ile Hash Match Join işlemi ile birleştirilmiştir. Şimdi sorgumuza Fast 5 değerini ekleyerek SQL Servera ilk 5 kaydın en hızlı geleceği şekilde sorgumuzun Execution Planını optimize ettirelim ve çıkan Execution Planı inceleyelim.
Yukarıdaki sorgumuza farklı olarak sadece option(fast 5) operatörünü ekledikten sonra şimdi Execution Planımızdaki değişiklikleri inceleyelim.
Yukarıdaki resimdeki Execution Planımızı incelediğimizde öncekine benzer olarak Sales.SalesOrderDetail tablosundaki veriler Clustered Index Scan işlemi ile okunup Compute Scalar operatörü ile tabloda bulunan Computed Column (Hesaplanmış Sütun) değeri hesaplanarak elde edilen sonuç kümesi önceki Execution planımızdan farklı olarak Production.Product tablosu üzerinde Clustered Index Seek işlemi yapılmış ve elde edilen sonuçlar Nested Loop Join operatörü ile birleştirilmiştir.
Aslında iki Execution Planımızda farklı olan kısımları incelediğimizde ilk planda Production.Product tablosu üzerinde Clustered Index Scan işlemi yapılmıştır. SQL Serverın bunu seçmesinin sebebi bu tablodaki tüm kayıtlara erişmemiz gerektiğinden dolayıdır ve bu sebeple SQL Server Scan işlemini daha hızlı sonuçlandıracağı için Clustered Index Scan işlemini tercih etmiştir. Fakat Fast 5 seçeneğini kullandığımız sorgumuzda Product tablosu üzerinde Clustered Index Scan yerine Clustered Index Seek işlemi tercih edilmiştir. Bunun sebebi ise Fast 5 operatörünü kullandığımız için SQL Server ilk 5 kaydı en hızlı getirmek için Clustered Index Seek işlemini tercih etmesidir. Genel kanı olarak Seek işleminin Scan işlemine göre daha iyi olduğu düşünülse bile Seek işleminin yapıldığı veri kümesi büyüdükçe sorgumuzun performansı da düşecektir. Aynı zamanda iki Execution Plan arasındaki bir diğer fark ise seçilen Join tipidir. İlkinde Hash Match Join seçilmesinin sebebi sıralı olmayan iki büyük veri kümesinin birleştirilmesidir. Fakat ikinci Execution planda ise Nested Loop Join seçilmiştir. Bunun sebebi ise Fast 5 ile yaptığımız optimizasyonda SQL Server 5 kaydın okunması senaryosuna göre sorgumuzun Execution planını optimize etmiş ve Sales.SalesOrderDetail gibi büyük bir tablo ile 5 kayıt içeren bir veri kümesinin birleştirilmesinde doğal olarak Nested Loop Join işlemini seçmiştir.
Fakat Fast 5 seçeneği yerine sonuç kümesine yakın bir değer kullanmış olsaydık SQL Server Execution Planı değiştirmeyecekti. Örneğin aynı sorgumuzu Fast 1000 olarak çalıştırıp Execution planını inceleyelim.
Fast N operatörü özellikle bazı durumlarda sorgu performansını beklenenden fazla artırmaktadır. Örneğin sorgularımızda top kullandığımızda gelen sonuç kümesinin sıralı olması önemli değilse ve bu sebeple order by operatörünü kullanmıyorsak Fast N operatörü performans açısından yararlı olacaktır. Şimdi bunu bir örnek üzerinde görelim.
Yukarıdaki iki sorgumuzdan da 5 kayıt gelecektir. Şimdi sorgularımızı çalıştırdıktan sonra sonuçları IO açısından değerlendirelim.
Yukarıdaki resimde gösterilen IO sonuçlarını incelediğimizde sadece Top 5 ile çalıştırdığımız sorgumuzdaki logical read değeri 468 iken Top 5 operatörünü aynı yazanda Fast 5 ile kullandığımızda ise logical read değerimiz 10 olacaktır.
SQL Serverda Execution Plan'a müdahale ederken kullanılan faydalı kullanımlardan biri de Fast N seçeneğidir. Sıkça karıştırılan bu operatörü kullanarak, SQL Serverın sorgu sonucunda gösterilecek olan sonuç kümesinin içinde N (N pozitif bir sayı) tane kaydı en hızlı getirecek şekilde Execution Planı optimize etmesini sağlayabiliriz. Fakat dikkat edilmesi gereken nokta burada verilen N pozitif bir sayı olmakla beraber gösterilecek kayıt sayısı ile alakalı değildir. Şöyle ki sorgumuzun sonucunda 1000 tane kayıt döndüğü durumda bu 1000 kaydın ilk 10 tanesinin olabilecek en hızlı bir şekilde ekrana getirilmesi ve kalan 990 tanesinin de ilk 10 tane hızlı bir şekilde gösterildikten sonra normal bir şekilde ekranda gösterilmesi isteniyorsa SQL Server'da bulunan Fast N seçeneği kullanılarak bu işlem çok daha performanslı bir şekilde gerçekleştirilebilmektedir. Ancak bu operatör çoğu zaman kayıt kümesinin N tane kayıt ile sınırlandırılacağı olarak düşünülmektedir. Bu yanılgıya düşülmemeli ve buna göre sorgular yazılmalıdır.
Şimdi Fast N operatörünün nasıl kullanıldığını bir örnek üzerinde görelim. İlk sorgumuzda Fast N operatörünü kullanmadan Execution Planımızı inceleyelim daha sonra aynı sorgumuzu Fast N operatörünü kullanarak SQL Server'ın kullanacağı Execution Planı inceleyelim ve karşılaştıralım.
1select *
2from Production.Product p
3inner join Sales.SalesOrderDetail sod
4on p.ProductID = sod.ProductID
2from Production.Product p
3inner join Sales.SalesOrderDetail sod
4on p.ProductID = sod.ProductID

Yukarıdaki resimde sorgumuzun Execution planını incelediğimizde Sales.SalesOrderDetail tablosundaki veriler Clustered Index Scan işlemi ile okunup Compute Scalar operatörü ile tabloda bulunan Computed Column (Hesaplanmış Sütun) değeri hesaplanarak elde edilen sonuç kümesi ile Production.Product tablosu üzerinde yapılan Clustered Index Scan işleminin sonucu ile Hash Match Join işlemi ile birleştirilmiştir. Şimdi sorgumuza Fast 5 değerini ekleyerek SQL Servera ilk 5 kaydın en hızlı geleceği şekilde sorgumuzun Execution Planını optimize ettirelim ve çıkan Execution Planı inceleyelim.
1select *
2from Production.Product p
3inner join Sales.SalesOrderDetail sod
4on p.ProductID = sod.ProductID
5option(fast 5)
2from Production.Product p
3inner join Sales.SalesOrderDetail sod
4on p.ProductID = sod.ProductID
5option(fast 5)

Yukarıdaki resimdeki Execution Planımızı incelediğimizde öncekine benzer olarak Sales.SalesOrderDetail tablosundaki veriler Clustered Index Scan işlemi ile okunup Compute Scalar operatörü ile tabloda bulunan Computed Column (Hesaplanmış Sütun) değeri hesaplanarak elde edilen sonuç kümesi önceki Execution planımızdan farklı olarak Production.Product tablosu üzerinde Clustered Index Seek işlemi yapılmış ve elde edilen sonuçlar Nested Loop Join operatörü ile birleştirilmiştir.
Aslında iki Execution Planımızda farklı olan kısımları incelediğimizde ilk planda Production.Product tablosu üzerinde Clustered Index Scan işlemi yapılmıştır. SQL Serverın bunu seçmesinin sebebi bu tablodaki tüm kayıtlara erişmemiz gerektiğinden dolayıdır ve bu sebeple SQL Server Scan işlemini daha hızlı sonuçlandıracağı için Clustered Index Scan işlemini tercih etmiştir. Fakat Fast 5 seçeneğini kullandığımız sorgumuzda Product tablosu üzerinde Clustered Index Scan yerine Clustered Index Seek işlemi tercih edilmiştir. Bunun sebebi ise Fast 5 operatörünü kullandığımız için SQL Server ilk 5 kaydı en hızlı getirmek için Clustered Index Seek işlemini tercih etmesidir. Genel kanı olarak Seek işleminin Scan işlemine göre daha iyi olduğu düşünülse bile Seek işleminin yapıldığı veri kümesi büyüdükçe sorgumuzun performansı da düşecektir. Aynı zamanda iki Execution Plan arasındaki bir diğer fark ise seçilen Join tipidir. İlkinde Hash Match Join seçilmesinin sebebi sıralı olmayan iki büyük veri kümesinin birleştirilmesidir. Fakat ikinci Execution planda ise Nested Loop Join seçilmiştir. Bunun sebebi ise Fast 5 ile yaptığımız optimizasyonda SQL Server 5 kaydın okunması senaryosuna göre sorgumuzun Execution planını optimize etmiş ve Sales.SalesOrderDetail gibi büyük bir tablo ile 5 kayıt içeren bir veri kümesinin birleştirilmesinde doğal olarak Nested Loop Join işlemini seçmiştir.
Fakat Fast 5 seçeneği yerine sonuç kümesine yakın bir değer kullanmış olsaydık SQL Server Execution Planı değiştirmeyecekti. Örneğin aynı sorgumuzu Fast 1000 olarak çalıştırıp Execution planını inceleyelim.
1select *
2from Production.Product p
3inner join Sales.SalesOrderDetail sod
4on p.ProductID = sod.ProductID
5option(fast 1000)
2from Production.Product p
3inner join Sales.SalesOrderDetail sod
4on p.ProductID = sod.ProductID
5option(fast 1000)

Fast N operatörü özellikle bazı durumlarda sorgu performansını beklenenden fazla artırmaktadır. Örneğin sorgularımızda top kullandığımızda gelen sonuç kümesinin sıralı olması önemli değilse ve bu sebeple order by operatörünü kullanmıyorsak Fast N operatörü performans açısından yararlı olacaktır. Şimdi bunu bir örnek üzerinde görelim.
01set statistics io on;
02
03select top 5 p.*
04from Production.Product p
05inner join Sales.SalesOrderDetail sod
06on p.ProductID = sod.ProductID
07
08
09select top 5 *
10from Production.Product p
11inner join Sales.SalesOrderDetail sod
12on p.ProductID = sod.ProductID
13option(fast 5)
02
03select top 5 p.*
04from Production.Product p
05inner join Sales.SalesOrderDetail sod
06on p.ProductID = sod.ProductID
07
08
09select top 5 *
10from Production.Product p
11inner join Sales.SalesOrderDetail sod
12on p.ProductID = sod.ProductID
13option(fast 5)
Yukarıdaki iki sorgumuzdan da 5 kayıt gelecektir. Şimdi sorgularımızı çalıştırdıktan sonra sonuçları IO açısından değerlendirelim.

Yukarıdaki resimde gösterilen IO sonuçlarını incelediğimizde sadece Top 5 ile çalıştırdığımız sorgumuzdaki logical read değeri 468 iken Top 5 operatörünü aynı yazanda Fast 5 ile kullandığımızda ise logical read değerimiz 10 olacaktır.