
Bu makalede MSSQL Server Execution Plan Repartition Streams Operatörünü detaylı bir şekilde görmüş olacağız. Paralelizmin kullanıldığı Execution planlarda sık kullanılan bir diğer operatör de Repartition Streams operatörüdür. Bu operatör diğer operatörlerden farklı olarak veri kümesini birden fazla parçaya bölerek işlem yaparken yine çıktısını birden fazla veri kümesi olarak verebilmektedir. Dikkat ederseniz Repartition Streams operatörü işlev olarak özellikle Distribute Streams operatörüne çok benzemektedir. Fakat aralarındaki fark Repartition Streams operatörü çıktısını gerekirse sıralayabilirken, Distribute Streams operatörü ise işlem yaparken verinin geldiği sırayı değiştirmeden korumaktadır. Bu sebeple sorgularımızda eklediğimiz sıralama operatörü bu iki operatörden hangisinin kullanılabileceğini de etkileyecektir.
Buraya kadar Execution planda sık kullanılan paralelizm operatörlerine değindik. Şimdi bu operatörleri kullanacak bir sorgu yazıp Execution planımızı inceleyelim.
SELECT *
FROM Sales.SalesOrderDetail sod
RIGHT JOIN Production.Product p
ON sod.ProductID = p.ProductID
ORDER BY p.ProductID DESC
Yukarıdaki sorgumuzun Execution planı aşağıdaki gibi olacaktır.

Sorgumuzun Execution planını incelediğimizde Query Optimizer’ın paralel bir Execution planı tercih ettiğini görebiliriz. Execution planımızın detaylarını incelediğimizde öncelikle Product tablosundaki kayıtlar okunmuş ve bunların işlenmesi için Distribute Streams operatörü kullanılmıştır. Bildiğiniz gibi Distribute Streams operatörü üzerinde işlem yaptığı veri kümesini birden fazla Thread ile okuyup işlem yapabilmektedir. Sorgumuzda Distribute Streams tarafından kullanılan veri kümesi Production. Product tablosunu temsil etmektedir. Burada Production.Product tablosunun çok büyük olmadığını ve Paralelizme ihtiyaç duymayacağını düşünebilirsiniz. Fakat bir sorgu da paralelizm kullanılıp kullanılmayacağına herhangi bir operatörün değil tüm sorgunun maliyetine bakılarak karar verilir. Bir sonraki kısımda ise Sales.SalesOrderDetail tablomuzdan kayıtlar Clustered Index Scan işlemi ile okunmuştur. Bu defa kayıtlar Repartition Streams operatörü kullanılarak okunmuştur. Bunun sebebi ise Sales.SalesOrderDetail tablosunun boyutunun büyük olması ve okunan veri kümelerinin paralel bir şekilde okunup aynı şekilde paralel olarak Sort yani sıralama işleminin de paralel yapılmasıdır. Sort işlemi de aynı şekilde Execution planımızda tercih edilen Merge Join işleminin yapılması için zorunludur. Fakat sorgumuzda dikkat ederseniz sıralama işlemini Production.Product tablosundaki ProductId kolonuna göre yapmamıza rağmen burada Sort operatörü kullanılmadı. Sebebi sizin de tahmin edeceğiniz üzere zaten Clustered Index Scan işlemi ile okunan kayıtların ProductId kolonuna göre sıralı olmasıdır.
Execution planımızın alt kısmında bulunan iki tane Compute Scalar operatöründen bir tanesi tablomuzda bulunan Computed Column değeri için kullanılırken diğeri ise veri tipi dönüşümü için kullanılmaktadır. Execution planımızdaki bir diğer operatör olan Merge Join ise iki tablomuzda bulunan kayıtların birleştirilmesi için kullanılmıştır. Daha sonra çıktısı paralel olan Merge Join işleminin sonucunda Gather Streams operatörü kullanılarak sorgumuzun nihai sonucu elde edilmiştir.
Sorgumuzun Execution planını incelediğimizde paralelizm kullandığını görmüş olduk. Paralelizm için SQL Server’ın birden fazla Thread kullanabileceğini söylemiştik. SQL Server’ın operatörlerdeki işlemi kaç Thread ile kaçarlı veri kümelerine böldüğünü operatörlerimizin özelliklerinden görebiliriz. Örneğin Production.Product tablosundan paralel bir şekilde veri okumak için kullanılan Distribute Streams operatörüne sağ tıklayarak Properties penceresini açalım ve bu operatörün özelliklerini inceleyelim.

Yukarıdaki resimde gördüğümüz gibi Distribute Streams operatörünün özelliklerinde görüleceği üzere Actual Number of Batches kaç tane Thread kullanıldığını yani diğer bir ifadeyle bu işlemin kaç parçaya bölünerek yapıldığını gösterirken, Actual Number of Rows kısmını incelediğimizde her bir Thread tarafından toplam okunan kayıt sayısını görebiliriz. Dikkat ederseniz her Thread hemen hemen eşit sayıda kayıt okuması yapmıştır. Bunun sebebi ise her Thread ‘in işini aynı zamanda bitirebilmesidir. Son olarak Actual Number of Rows değerindeki Thread 0 olarak görünen kısmında hiç kayıt olmamasının sebebi bu işlemin diğer işlemleri yönetmesidir.
Yukarıdakine benzer olarak sorgumuzdaki diğer paralelizm operatörü olan Repartition Streams operatörünün de Properties penceresini aşağıdaki gibi inceleyebiliriz.

Yukarıdaki resimde gördüğümüz gibi bu defa Sales.SalesOrderDetail tablosundan yapılan okuma 4 parçaya bölünerek paralel yapılmıştır. Paralelizm operatörlerimizin özellikler penceresinden kaç tane Thread kullanıldığını ve kaçar kayıt okuduklarını görebiliyoruz. Ayrıca bu operatörlerin Properties penceresinin en alt kısımdaki özelliklerini incelediğimizde karşımıza aşağıdaki gibi bir kaç tane daha özellik gelecektir.

Yukarıdaki resimde gördüğümüz gibi operatörümüzün Physical Operation özelliğinde paralelizmin kullanıldığını görebiliyoruz. Ayrıca benzer olarak Paralel adında olan diğer özelliği ise True değerini taşımaktadır. Fakat bu özelliklerden ziyade Partition Columns özelliğini incelediğimizde bu kısım paralelizm için küçük parçalara bölünecek tablonun bilgileriyle bölümleme işleminin hangi kolondaki değere göre yapılacağı bilgisini tutmaktadır. Örneğin bizim operatörümüz için Sales.SalesOrderDetail tablosundaki ProductId kolonuna göre veri kümemiz bölümlere ayrılacaktır.
Bu makalede execution yapılarında görülen Repartition Streams ifadesine değinmiş olduk. Başka bir makalede görüşmek dileğiyle..
“Lokmân oğluna öğüt verirken ona şöyle dedi: “Sevgili oğlum! Allah’a ortak koşma; çünkü O’na ortak koşmak kesinlikle çok büyük bir haksızlıktır.””Lokman-13