MSSQL Server Execution Plan’da Lazy Spool Kavramı

Bu makalede MSSQL Server Spool kavramlarını sırasıyla detaylı bir şekilde ele almış olacağız. Spool kavramı sql server yapısında performansı arttırmak için kullanılan bir yapı olarak karşımıza çıkmaktadır. Genellikle execution plan yapılarında karmaşık olan işlemlerinde karşımıza çıkan bir yapıdır.

SQL Server’da Spool operatörleri, sorgu işlemcisinin (Query Processor) ara sonuçları geçici olarak saklayıp (genellikle tempdb üzerinde) tekrar kullandığı mekanizmalardır. Temel mantığı, “bir kez hesapla, defalarca kullan” prensibine dayanır.

Spooling genellikle performansı artırmak için kullanılır ancak bazen büyük veri setlerinde disk I/O yükü yaratarak darboğaz oluşturabilir.

Sql server yapısında bir veri okunduktan sonra tekrar kullanılma ihtimaline karşı okunan verinin Tempdb veritabanında tutulması işlemidir. Ekstra bir maliyet oluşmasın diye tabloya tekrardan ihtiyaç duyulma ihtimaline karşı geliştirilmiş olan bir yapıdır.

Birden fazla spool operatörü vardır. Bunlar:

  • Lazy Spool
  • Eager Spool
  • Table Spool
  • Row Count Spool
  • Index Spool

Genellikle spool operatörleri okuma yapan operatörlerle birlikte kullanılmaktadır.

Spool operatörlerinin veri okuması yapan operatörlerle beraber kullanıldığını söylemiştik. Fakat SQL Server’da Execution plan operatörleri başka bir operatör vasıtasıyla veriyi okurken iki yöntem kullanabilirler. Bunlardan ilki veri kümesinde bulunan kayıtlarımızın teker teker okunup işlenmesi işlemidir. Bu şekilde çalışan operatörlere Non Blocking operatörler denmektedir. Bu operatörlere örnek olarak Nested Loop Join operatörünü verebiliriz. Çünkü bildiğiniz gibi Nested Loop Join operatörü veri kümesi üzerinde her satır için işlem yapan bir operatördür.

İkinci bir veri okuma yöntemi ise veri kümesindeki verilerin teker teker değil tüm kayıtların aynı anda okunmasıdır. Bu şekilde çalışan operatörlere ise Blocking operatörleri denmektedir. En sık kullanılan Blocking operatörü ise Sort operatörüdür. Çünkü Sort yani sıralama işleminin yapılabilmesi için veri kümemizdeki kayıtların teker teker değil hepsinin beraber okunup değerlendirmesi gerekmektedir.

Şimdi execution plan üzerinde olan Lazy Spool(Table Spool) operatörünü detaylı bir şekilde ele alalım:

Dikkat etmemiz gereken bir diğer nokta ise Execution planımızda kullanılan Table Spool (Lazy Spool) operatörünün üzerinde hem Table Spool hem de Lazy Spool ifadesinin bulunmasıdır. Bunun sebebi ise her ikisi de Spool işlemi yapan Table Spool ve Lazy Spool beraber kullanılabilen operatörlerdir. Çünkü Table Spool operatörü fiziksel bir operatör iken Lazy Spool operatörü ise mantıksal (logical) operatördür. Fiziksel ve mantıksal operatörler arasındaki fark ise mantıksal operatörler yapılacak olan işlemi tanımlarken, fiziksel operatörler ise buna uygun olarak işlemi yapan operatörleri belirtmektedir. Yani Table Spool (Lazy Spool) ile yapılacak mantıksal işlemin Lazy Spool olduğunu görebiliyoruz. Lazy Spool operatörü ile verinini sırası ile okunacağını belirtiyoruz. Fakat verinin teker teker okunup Tempdb veritabanında bir tabloda saklanması işlemini fiziksel olarak yapan operatör ise Table Spool operatörüdür.

Lazy Spool Non-blocking operatör olup Eager Spool’dan farklı olarak kayıtların hepsini bir defada değil sadece ilgili operatör ihtiyaç duyduğunda teker teker okuyup yine geçici bir alanda saklayacaktır.

Lazy Spool bir önceki operatörden bir talep geldiğinde sadece o satırı alır ve tempdb’ye atar. (Nested Loop operatör’ünde satır satır okuma işlemi yapıldığı için görebilirsiniz.)

Execution planımızda birden fazla Spool operatörünün olması birden fazla veri kümesinin okunup Tempdb veritabanında tutulduğu anlamına gelmez. Çünkü Spool işleminin temel amacı bir veriye birden fazla defa erişme ihtiyacımızın olduğu durumlarda her defasında veri kaynağından bu veriyi okumak yerine bunun Spool işlemi ile depolanması ve ihtiyaç halinde kullanılmasıydı.

Yukarıdaki açıklamayı destekleyecek table spool’ların diğer spoolları referans aldığını görmüş olacağız. Yukarıdaki ilk table spool kavramının properties ekranına tıkladığımızda node id değerinin 2 olduğunu görmüş oluyoruz. Bu yapı aslında ilk lazy spool operatörüdür.

Şimdi diğer lazy spool operatör’e tıklayalım yukarıdaki Node ID değerini referans aldığını görmüş olacağız.

Yukarıdaki iki Primary Node ID değeri ilk oluşturulan lazy spool değerini tekrardan kullanmaktadır.

Spool her zaman “kötü” değildir, ancak bazen eksik bir index’in habercisidir:

  • Tempdb Şişmesi: Spool işlemleri tempdb’de gerçekleşir. Eğer Spool operatörü milyonlarca satır işliyorsa, tempdb üzerinde ciddi bir yük ve yavaşlama oluşturur.
  • Index Eksikliği: Eğer planınızda sürekli Index Spool görüyorsanız, SQL Server size şunu demek istiyordur: “Burada bir index olsaydı ben bunu kendim oluşturmak zorunda kalmazdım.” Bu durumda ilgili kolonlara kalıcı bir index eklemeyi düşünmelisiniz. Index spool makalesi okunabilir.
  • Eager Spool ve Engelleme: Eager Spool, altındaki tüm veriyi okumadan üst tarafa veri göndermediği için sorgunun “ilk satırı getirme süresini” (Time to First Row) uzatabilir.

Spool, SQL Server’ın “not defteri” gibidir. Karmaşık işlemlerde ara sonuçları unutmamak için not alır. Eğer not defteri çok kalınlaşıyorsa (büyük veri), asıl kütüphaneyi (indexleri) düzenleme vaktiniz gelmiş demektir.

DurumGenellikle…Aksiyon Gerekli mi?
Index SpoolEksik Index belirtisidir.Evet, mutlaka index eklemeyi düşünün.
Büyük Verili Eager SpoolTempdb yükü ve yavaş başlangıç.Evet, sorgu mantığını veya Join’leri inceleyin.
Küçük Verili Lazy SpoolHafif bir optimizasyon.Hayır, genellikle zararsızdır.
Recursive CTE / Window Func.Mimari zorunluluk.Hayır, SQL Server’ın çalışma şekli budur.

Lazy Spool, genellikle bir Nested Loops Join’in iç kısmında (Inner Side) görülür. Amacı, aynı değerler için alt operatörü tekrar tekrar çalıştırmaktır.

  • Ne Zaman Aksiyon Alınmalıdır
    • Eğer Lazy Spool, çok fazla satır için defalarca (Execution count) çalışıyorsa.
    • Altındaki maliyet (Cost) yüksekse.
  • Genellikle bu operatör, SQL Server’ın “Ben bu veriyi bir yere kaydedeyim de sürekli aynı şeyi aramayayım” deme şeklidir. Eğer ilgili tabloda uygun bir Index olsaydı, SQL Server Spool kullanmak yerine doğrudan Index üzerinden arama (Seek) yapardı. Eksik indexleri kontrol edin.

Özetle Ne Yapmalısınız:

  1. Execution Count değerine bakın. Eğer Spool operatörü milyonlarca kez tetikleniyorsa, bu bir sorundur.
  2. Actual Number of Rows ile Estimated arasındaki farka bakın. İstatistikler güncel değilse SQL Server yanlışlıkla Spool kullanmaya karar vermiş olabilir. UPDATE STATISTICS komutunu deneyebilirsiniz.
  3. Tempdb üzerindeki PAGELATCH_IO gibi beklemeleri (waits) kontrol edin. Eğer Spool diske yazıyorsa, sistemi yavaşlatır.

Not: Row Count Spool Sadece satırların var olup olmadığını veya kaç adet olduğunu kontrol eder. Verinin kendisini değil, sadece sayısını veya varlık bilgisini saklar.

Bu makalede MSSQL Server Execution Plan Lazy Spool Kavramı detaylı bir şekilde görmüş olduk.

Başka bir makalede görüşmek dileğiyle…

*Göklerde ve yerde ne varsa hepsi Allah’ındır. Allah’ın ilmi ve kudreti her şeyi kuşatmıştır. Nisa-126*

Author: Yunus YÜCEL

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir