MSSQL Server Execution Plan AND ve OR Operatörlerin Mantığı

Sorgu iyileştiricisi (Query Optimizer), bir sorguyu çalıştırırken en az maliyetli yolu seçmeye çalışır. Bu seçim sürecinde AND ve OR operatörleri, indekslerin verimliliğini doğrudan etkiler.

AND operatörü kullanıldığında, sonuç kümesinin her iki koşulu da sağlaması gerekir. SQL Server bu durumu bir “daraltma” fırsatı olarak görür.

Tablonuzda AddressID kolonu üzerinde bir Clustered Index olduğunu, City kolonunda ise hiçbir indeks olmadığını varsayalım.

Sorgu:

SELECT * FROM Person.Address WHERE AddressID < 1000 AND City = 'Ankara'

Execution Plan Davranışı:

  • Index Seek: SQL Server, Clustered Index’i kullanarak hızlıca 1000’den küçük olan kayıtları bulur.
  • Residual Predicate (Artık Filtre): İndeks üzerinden daraltılan bu küçük veri kümesi (örneğin 999 satır) RAM’e alınır. SQL Server, bu 999 satırı tek tek kontrol ederek City = ‘Ankara’ olanları ayıklar.
  • Sonuç: Planda Clustered Index Seek görünür. Çünkü SQL Server, “Zaten ID üzerinden alanı çok daralttım, kalan az sayıdaki veriyi manuel kontrol etmek tüm tabloyu taramaktan (Scan) çok daha ucuzdur” der.

SQL Server genellikle aynı tablo için birden fazla indeksi aynı anda kullanmak yerine, en hızlı sonucu verecek olan tek bir indeksi seçmeyi tercih eder.

  • SQL Server istatistiklerine bakar. Eğer AddressID < 1000 koşulu 999 satır getiriyorsa ama City = ‘Ankara’ koşulu sadece 5 satır getiriyorsa, SQL Server City üzerindeki indeksi kullanmaya karar verir.
  • City indeksi üzerinden Index Seek yapar, 5 satırı bulur. Bu satırların diğer bilgilerini (AddressLine1 vb.) getirmek için Key Lookup yaparak ana tabloya (Clustered Index) gider.
  • Planda bir Non-Clustered Index Seek ve yanında bir Key Lookup operatörü görürsünüz.

Bazen her iki koşul da veri kümesini ciddi oranda daraltıyorsa, SQL Server her iki indeksi de aynı anda kullanabilir.

  • İşleyiş:
    1. AddressID indeksi üzerinde bir Seek yapar (ID < 1000 olanların listesini alır).
    2. City indeksi üzerinde ayrı bir Seek yapar (Ankara olanların listesini alır).
    3. Merge Join veya Hash Match operatörü ile bu iki listede ortak olan (kesişen) kayıtları bulur.
  • Görünüm: Planda iki farklı koldan gelen Seek oklarının bir “Join” operatöründe birleştiğini görürsünüz.

AND kullanıldığında SQL Server en verimli yolu seçmeye çalışır. SQL Server önce Clustered Index Seek yaparak aralığı daraltır. Ardından, hafızaya aldığı bu satırlar üzerinde ikinci kolonun koşulunu kontrol eder (buna Residual Predicate denir).

OR operatörü, “koşullardan biri doğruysa getir” dediği için SQL Server’ın işini zorlaştırır. Aynı tablo yapısında: AddressID (Clustered Index) ve City (İndekssiz).

Sorgu:

SELECT * FROM Person.Address WHERE AddressID < 1000 OR City = 'Ankara'

Execution Plan Davranışı:

  • SQL Server, AddressID < 1000 kısmını indeksten bulabilir. Ancak, tablonun geri kalanında (örneğin ID’si 50.000 olan yerlerde) şehri ‘Ankara’ olan biri olup olmadığını bilemez.
  • Neden scan yapar City kolonunda bir indeks olmadığı için SQL Server, ‘Ankara’ değerini bulabilmek adına tablonun tamamını okumak zorundadır.
  • Planda Clustered Index Scan (Tablo Taraması) görürsünüz. Tek bir kolonun indekssiz olması, OR operatörü nedeniyle diğer kolonun indeks avantajını tamamen yok eder.

Eğer City kolonunda da bir Non-Clustered Index olsaydı, OR operatörü felakete yol açmazdı.

  • SQL Server, AddressID indeksinde bir Seek yapar, City indeksinde ayrı bir Seek yapar.
  • İki tarafın sonuçlarını (RID veya Primary Key üzerinden) birleştirir (Merge veya Hash Match).
  • Tablonun tamamını taramak yerine, iki koldan hızlıca gelen verileri birleştirerek yine performanslı bir sonuç üretir.

Özetle

Operatörİndeks Kullanımı (Seek/Scan)Neden?
ANDGenellikle Seek yapar.İndeksli kolon üzerinden alanı daraltıp, kalanları bellekte filtrelemek ucuzdur.
ORÇoğunlukla Scan yapar.Koşullardan biri indekssizse, SQL Server o kaydı kaçırmamak için tüm tabloyu okumak zorundadır.
OR (Her iki kolon indeksli)Seek + Seek yapabilir.SQL Server iki indeksi ayrı ayrı sorgulayıp sonuçları birleştirebilir.

Evet, SQL Server her türlü veri işlemesi için veriyi diskten RAM’deki “Buffer Pool” alanına taşır. Tooltip’teki Estimated Row Size ile satır sayısının çarpımı kadar veri RAM’de yer kaplar.

Implicit Conversion: Eğer OR veya AND içinde kullandığınız değerin tipi kolon tipiyle uyuşmuyorsa, SQL Server dönüşüm yapmak zorunda kalır. Bu işlem CPU maliyetini artırır ve bazı durumlarda Index Seek yapılmasını engelleyerek performansı düşürür.

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

    “Biz ona şah damarından daha yakınız.” Kaf-16

    Author: Yunus YÜCEL

    Bir yanıt yazın

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