MSSQL Server Composite  Index

Birden fazla kolonu bir ayara getirerek oluşturulan index Composite Index olarak adlandırılmaktadır. Tablo üzerinde tanımlanan index tek kolon üzerinden değil de birden fazla kolon üzerinden tanımlandıysa bu index türüne composite index denir.  SQL Server’da, composite index’te kolonların sırasına dikkat etmek oldukça önemlidir çünkü indeksin performansını doğrudan etkiler. Kolon sırasının doğru belirlenmesi, sorguların hızını artırabilir veya azaltabilir. İndekslerdeki kolon sırası, SQL Server’ın sorgularda veri arama ve sıralama işlemlerini nasıl gerçekleştireceğini belirler. Composite index’teki kolon sırası, aşağıdaki sebeplerle önemlidir:

Index kısıtlamalarında bahsettiğimiz gibi, bir tabloda en fazla 16 kolona kadar composite index tanımlanır ve 900 byte sınırını geçmemelidir. Hem clustered hem de non-clustered index’ler composite olarak tanımlanabilir. Bu index tanımında kolonların hangi sırada yazıldığı da çok önemlidir. Index performansının artması için çeşitliliği fazla olan kolon başa yazılmalıdır. Yani tablodaki verilere göre tekil veri sayısı fazla olan kolon başa yazılır.

 Aşağıdaki resimde görüldüğü gibi birden fazla kolun aynı index üzerinde oluşturulabilir.

Oluşturduğumuz nonclustered index’in boyutu 1700 byte’tan fazlaysa uyarı mesajı alırız. İnclude sütünlarıyla toplam boyutu 8060 byte olması gerekmektedir. Bu alan fazlalığından dolayı hata mesajı almaktayız. Genel olarak aşağıdaki komut satırında belirtildiği gibi tanımlanmaktadır.

CREATE NONCLUSTERED INDEX IX_IndexName ON IndexName (Column1, Column2)

Not: Composite index’te 16 kolon ve 900 byte sınırı olduğundan istediğimiz kadar kolon ekleyemeyiz. Kısıt olmasa dahi, index tanımımızda fazla kolon olması index boyutunu o kadar arttıracaktır ve yapılacak update, insert gibi işlemlerde index yeniden organize olacağından performans kaybına yol açacaktır.

1. İndeksin Kullanımını Etkiler

SQL Server, indekslerdeki kolonları soldan sağa doğru kullanır. Yani, indeksin ilk kolonuna göre sorgu filtrelenirse, SQL Server bu indeksi kullanabilir. Eğer sorgu sadece ikinci ya da üçüncü kolonu içeriyorsa, SQL Server bu indeksi kullanmakta zorluk çekebilir.

Örneğin, aşağıdaki composite index‘e sahip bir tabloyu düşünelim:

CREATE INDEX IX_Orders_CustomerID_OrderDate

ON Orders(CustomerID, OrderDate);

Bu indeks CustomerID ve OrderDate kolonlarını içerir. Ancak sorguların sıralamasına göre indeksin verimli kullanımı değişir:

  • İyi Kullanım:
SELECT * FROM Orders WHERE CustomerID = 1 AND OrderDate > '2025-01-01';

Bu sorgu, her iki kolon olan CustomerID ve OrderDate’i kullandığı için IX_Orders_CustomerID_OrderDate indeksi çok verimli çalışacaktır.

  • Zayıf Kullanım:
SELECT * FROM Orders WHERE OrderDate > '2025-01-01';

Bu sorgu yalnızca OrderDate kolonunu kullandığı için, IX_Orders_CustomerID_OrderDate indeksi verimli bir şekilde kullanılmayabilir. Çünkü indeksin ilk kolonu olan CustomerID sorguda kullanılmadığı için, SQL Server tüm indeksi taramak zorunda kalabilir.

2. Sorgu Planlarını ve Performansı Etkiler

Kolonların sırası, SQL Server’ın sorgu planı oluşturmasını etkiler. SQL Server, composite index‘i oluştururken, kolonların sırasına göre sorgu filtrelemelerini daha verimli hale getirebilir.

  • En İyi Durum: İndeksin ilk kolonu, en sık sorgularda kullanılan kolon olmalıdır. Bu, SQL Server’ın bloom filter gibi optimizasyon tekniklerini kullanarak arama süresini kısaltmasını sağlar.
  • En Kötü Durum: Eğer ilk kolon, nadiren kullanılan bir kolon olursa ve diğer kolonlar daha yaygın kullanılıyorsa, indeks hala kullanılabilir, ancak verimlilik düşer. Bu durum, indeksin yanlış kullanılmasına ve gereksiz veri taramalarına yol açar.

3. Prefix (Ön Ek) Özelliği

Composite index’lerde kolon sırası, prefix özelliği ile ilgilidir. Eğer bir sorgu, indeksin ilk kolonunu içeriyorsa, SQL Server diğer kolonlara da bakabilir, ancak kolon sırasına dikkat etmelidir.

Örneğin, CustomerID, OrderDate şeklinde sıralı bir composite index varsa:

İlk Kolon: Sadece CustomerID‘yi sorgulayan bir sorgu, bu indeksi tamamen kullanabilir.

İkinci Kolon: OrderDate’yi sorgulayan bir sorgu ise, indeksi verimli kullanamaz çünkü CustomerID’yi filtrelemeden sadece OrderDate’i kullanmak için indeksi tam olarak kullanmak mümkün olmayacaktır.

4. Sıralama ve Gruplama İşlemleri

İndeksler, yalnızca filtreleme değil, aynı zamanda sıralama ve gruplama işlemleri için de kullanılabilir. Eğer bir sorgu ORDER BY veya GROUP BY içeriyorsa, kolon sırası da bu işlemleri etkiler.

SELECT * FROM Orders

WHERE CustomerID = 1

ORDER BY OrderDate;

Eğer indeksi CustomerID, OrderDate şeklinde oluşturduysanız, bu indeks, sıralama işlemi için de verimli bir şekilde kullanılacaktır. Ancak eğer OrderDate’i ilk kolon olarak koysaydınız, sıralama işlemi için indeksi kullanmak zorlaşırdı.

5. Wildcard ve LIKE İfadeleri

Eğer LIKE ifadeleri kullanıyorsanız, indeksin ilk kolonunun kullanılması gerektiğini unutmamalısınız. Örneğin:

SELECT * FROM Orders WHERE CustomerID LIKE 'A%' AND OrderDate > '2025-01-01';

Burada, CustomerID kolonu LIKE ifadesi ile kullanıldığı için, indeksin bu kolonla başlaması verimli olacaktır.

Kolon Sırasını Doğru Seçmenin İpuçları

  1. İndeksin ilk kolonuna, sorgularınızda en sık kullanılan kolonları koyun. Bu, indeksi daha verimli hale getirecektir.
  2. Kolon sırasını, sıkça WHERE, JOIN, ve ORDER BY ifadelerinde kullanılan kolonlar doğrultusunda belirleyin. Bu, SQL Server’ın sorgu optimizasyonunu daha verimli hale getirebilir.
  3. Sorgularınızda birçok kolon filtrelemesi varsa, composite index oluştururken, sorgularda daha önce filtrelenmiş kolonları ilk sıraya yerleştirin.
  4. Daha fazla kolon içeren indeksi tercih ederken, indeksin büyüklüğünü ve performansını göz önünde bulundurun. Fazla sayıda kolon indeks performansını olumsuz etkileyebilir.

Composite Index‘te kolonların sırasına dikkat etmek, sorgu performansını doğrudan etkiler. İlk kolon her zaman en sık kullanılan kolon olmalıdır. İndeksin doğru kullanılabilmesi için sorgularda sıklıkla kullanılan kolonların, indeksi oluşturan kolonlar arasında ilk sırada yer alması gereklidir. Kolon sırasının yanlış belirlenmesi, indeksin verimsiz kullanılmasına ve sorgu performansının düşmesine yol açar. Kısacası eğer composite indexsin ilk kolonu kullanılmazsa sql server ilk kolonu kullanmadan 2. ve 3. satıra erişemez ve erişmekte güçlük çeker. Sorgumuzun en performanslı bir şekilde çalışması için tüm kolonların sorgumuzda olması gerekmektedir. Leaf seviyesinde composite indexsin tüm kolonların yanında aynı zamanda clustered indexs key’i veya RID saklanmaktadır. Sorgumuzda ilk kolon yoksa sql server genellikle index seek yerine index scan yapısını tercih etmektedir.

NOT: Bir composite index (bileşik indeks), birden fazla sütunu içeren bir indeks türüdür. Eğer bir composite index’in unique (benzersiz) olmasını istiyorsanız, aşağıdaki şartları sağlamalısınız.

NOT: Composite index kendi içinde composite istatistik taşır mı? Hayır yalnızca ilk sütuna ait histogram içerir. Peki kombinasyon bilgisi içerir mi? Evet density vector ile A,B seçiciliği hesaplanabilir.
A,B için detaylı histogram istersem? Manuel olarak composite istatistik oluşturmalısın.

Composite indexlerde ilk kolunun yanına ikinci kolun eklendiğinde select sorgularımızda sadece 2 kolon tek çağrılıyorsa burada sql server index seek işlemi yapar.

Sorgunun devamında order by işlemi yapılırsa keylookup işlemi yapılmaktadır. Bu yapını oluşmasını sebebi SorguTarihi kolonunun olmasından dolayıdır.

İlgili index’in unique olması için tek tek sütunların unique olması gerekmez, ancak indeks içindeki tüm sütunların birleşimi (kombinasyonu) benzersiz olmalıdır. Yani, her satır için aynı sütun değer kombinasyonu tekrar etmemelidir. Tek tek sütunların unique olması gerekmez, ancak bileşik indeks içindeki tüm sütun kombinasyonları benzersiz olmalıdır.

NOT: Eğer AND ile bağlı iki kolona göre WHERE koşulu varsa ve bu iki kolon için sıralı (ordered) bir composite index varsa (örneğin CREATE INDEX ix ON tablo(a, b)), SQL Server bu iki şartı tek bir index seek ile yerine getirebilir. Yani:
• a değerini bulur,
• b kolonuna zaten fiziksel olarak o noktada eriştiği için tekrar arama yapmaz.

Bu iki şartı tek seferde, tek index ile karşılar.

NOT: Aşağıdaki komut aracılığıyla index oluşturulduğunda artık index her güncelleme veri ekleme silme işleminden sonra istatistikler güncellenecektir.

CREATE INDEX IX_Customer_Name
ON Customer(Name)
WITH (STATISTICS_NORECOMPUTE = OFF);

STATISTICS_NORECOMPUTE = OFF demek:
SQL Server bu indeksin istatistiklerini kendisi izler ve gerektiğinde otomatik olarak günceller.

=ON ifadesinin denilmesi artık istatistiklerin otomatik olarak güncellenmeyeceği manuel bir şekilde güncelleme işlemi yapmamız gerekmektedir. Bu ifade genelde büyük bir index’in fullscan yapıldıktan sonra istatistiklerin artık güncellenmek istemeyişidir.

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

“Lokmân, “Sevgili oğlum” (dedi), “Yaptığın iş bir hardal tanesi ağırlığında bile olsa, bir kayanın içinde saklansa veya göklerde yahut yerin dibinde bulunsa yine de Allah onu açığa çıkarır. Kuşkusuz Allah her şeyi bütün gizlilikleriyle bilir, O her şeyden haberdardır.”Lokman-16

Author: Yunus YÜCEL

Bir yanıt yazın

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