ĠNDEKS

advertisement
ĠNDEKS
İndeks‟ler, tablolardan veri çekmek için sorgular çalıştırılırken, gereken süreyi
azaltmak için kullanılır. Birkaç kayıt için bu süre pek önemli değilken, kayıt sayısı onbinlere,
milyonlara çıktığında hayati öneme sahiptir.
INDEKS KULLANIMI
SQL sorguları çalıştırıldığında veriler tablo üzerinden iki yöntemle alınır.
Birincisi, tablo baştan sona kadar taranır ve istenilen veri alınır. Bu yöntem table scan
(tablo tarama) olarak adlandırılır.
İkinci yöntem ise tablo üzerinde oluşturulan indeksler yardımıyla istenilen verilerin
toplanmasıdır.
Tablomuzdaki kayıt sayısı çok fazla olduğunda birinci yöntem doğal olarak
performans kaybına sebep olacaktır.
KÜTÜPHANE ÖRNEĞĠ
Bir örnek üzerinden indeks yapılarını anlamak daha kolay olacaktır. Bir kütüphaneyi
ele alalım. Kütüphaneyi kitaplara ilişkin bilgilerin saklandığı kitap tablosuna benzetebiliriz.
Kütüphanedeki görevlinin yeni gelen her kitabı bulduğu ilk boş yere koyduğunu
düşünelim. Bu şekilde kitaplar belli bir kurala göre dizilmiyorsa ortaya çıkan yapıya yığıt
(heap) denir.
Bu kütüphanede okurun aradığı kitabı bulabilmek için kütüphanedeki bütün kitapları
tek tek kontrol etmek gerekir. Bu duruma tablo taraması (table scan) denir. Eğer
kütüphanede birkaç yüz kitap varsa bu pek sorun değildir ama yüz binlerce kitabın bulunduğu
bir kütüphanede aranılan kitabı bulabilmek çok büyük bir sorun olacaktır.
Bu sorunu çözebilmek için akla gelen ilk yöntem kitapları raflara alfabetik sırada
koymak olacaktır. Kitapları bu şekilde sıraya konulursa kütüphanecimiz bütün kitapları
gözden geçirmeden okurun istediği kitabı daha hızlı bir şekilde bulabilir. “Ateşten Gömlek”
adlı bir kitabı arayan okur geldiğinde, kütüphaneci hemen rafların en başına yönelir. Bu
şekilde kitap tablosu üstünde kitap adları sütunu için bir Clustered Ġndeks tanımlamış oluruz.
Clustered İndeks, bir tablo üzerinde sadece bir tane tanımlanabilir ve verilerin bir niteliğine
göre fiziksel olarak sıralanmaları durumunu ifade etmek için kullanılır.
Ancak okur bazen de kitap adını bilmeden kitap isteyebilir. Örneğin “Mehmet Akif
Ersoy‟un şiir kitaplarını istiyorum” dediğinde kütüphaneci yeni bir sorunla karşılaşacak.
Kütüphaneci kitapları kitap adına göre dizdiğine göre bu sorun için yeni bir çözüm bulması
gerekecektir. Bu durumda kitap yazarlarından kitap adlarına geçişi sağlayacak bir liste tutmak
aklına gelecektir. Şu şekilde bir liste olsun;
Yazar Adı
…
Halide Edip Adıvar
Halide Edip Adıvar
Halide Edip Adıvar
…
Mehmet Akif Ersoy
Mehmet Akif Ersoy
…
Kitap Adı
…
Vurun Kahpeye
Ateşten Gömlek
Sinekli Bakkal
…
Safahat – I
Safahat – II
…
Bu liste için Non-Clustered İndeks diyeceğiz. Bir yazar adı sorulduğunda kütüphaneci
yazarın kitaplarının her birinin bulunduğu bölge hakkında fikir sahibidir. Nonclustered
İndeks‟ler, bir Clustered İndeks veya Heap üstünden hızlı olarak kayıtlara erişim sağlamak
üzere tanımlanır.
Kütüphaneci, yazar-kitap listesinin benzerini, Konu-Kitap, ISBN-Kitap, YayıneviKitap gibi diğer sütunlar için de gerektiğinde hazırlayabilir. Veritabanında bu şekilde belli
sayıda (MS-SQL 2005 veritabanında 249 adet) Nonclustered İndeks yer alabilir.
Bazı küçük tablolarda, tablo taraması daha hızlı sonuca ulaştırabilir. Veritabanı karzarar analizini yaparak hangi yöntem uygunsa o yöntem ile arama yapar.
HEAP (yığıt) : Kayıtların giriliş sırasına göre diske kaydedildiği yapıya HEAP (yığıt)
denir.
CLUSTERED INDEKS: Clustered İndeks‟te tabloda yer alan kayıtlar fiziksel olarak
indeks‟le tanımlı olan sütuna göre dizilirler. Bir tablo üzerinde en fazla bir tane Clustered
Indeks tanımlanabilir.
Genellikle, clustered indeks için tek satır döndürmeyen sütunlar tercih etmek yararlı
olacaktır. Çünkü clustered indeks özellikle aralık sorguları için yüksek performans sağlar.
Örneğin ürün tablosunda ürün adı bu iş için uygundur. Ama öte yandan mağazamızda
marklalar üzerinden bir gezinti kullanılıyorsa markakod sütununu clustered indeks yapmak
daha akıllıca olur.
(primary key constraint – unique constraint – unique – uniquefier (tekilleştirici)
Tablo üstünde clustered indeksin idğer indekslerden önce oluşturulmasında fayda
vardır. Çünkü diğer indekslerin tamamında bu indeksin oluşturduğu tekil değer kullanılır.
Clustered Indeks tanımlarken;
 Sık sorgulanan sütunlar
En çok hızlanması gereken sorgular göz önüne alınarak tanımlanması
gerekmektedir. WHERE kısmında sıkça geçen sütunlar, JOIN edilecek sütunlar,
BETWEEN ile aralık taraması yapılan sütunlar clustered indeks için tercih edilmesi
gereken sütunlardır.
 Boyutu küçük sütunlar
Çünkü bu sütuna ait bilgiler hem clustered hem de buna bağlı olacak nonclustered
indeksler için kullanılır. Bir indeks sayfasında daha fazla indeks yer alabilmesi için
indeks anahtarının küçük olması gerekmektedir.
 Daha az değişim gösteren sütunlar
Çok sık değişen bir anahtar, indekslerin çabuk yorulmasına (dağınıklaşmasına) yol
açar. Ayrıca her veri değişiminde indekslerin anahtarı değişince clustered indeks
verileri ve dolayısıyla nonclustered indeks verilerinin değişmesi gerekeceğinden sık
değişmeyen sütunların tercih edilmesi yaralı olur.
NONCLUSTERED INDEKS: Bir sütun üzerinden veri erişimi hızlandırılmak
isteniyorsa NONCLLUSTERED İNDEKS oluşturulabilir. Bir tablo üzerinde birden fazla
nonclustered indeks olabilir. Kendisi doğrudan veriye erişemez. Heap üstünden veya
Clustered İndeks üzerinden verilere erişebilir. Dolayısıyla performansı clustered indeks‟lerden
daha düşüktür.
Nonclustered İndeks tanımlarken;
 “Performans Kazanımı” ve “Tamirat Bedeli” dengesi
Tanımladığınız her indeks, bir taraftan veri okuma erişim süresini kısaltırken,
diğer taraftan veri ekleme, silme ve güncelleme esnasında veritabanını yoracaktır.
Bu nedenle çok fazla veri okuyan, az veri eklenen bir sistem üzerinde
çalışmıyorsanız gereksiz indeks tanımlamalarından kaçının.
 Arama argümanları
Clustered indeks dahilinde indeksleyemediğimiz WHERE ve JOIN gibi
sorgularda kriter olan sütunları nonclustered indeks olarak tanımlamak,
performansı arttıracaktır. Nonclustered indeksler özellikle tek satır veya birkaç
satırdan oluşan sonuçlar alan sorguları hızlandırmak için iyi bir yoldur.
 Yeterli Seçicilik
İndekslenecek sütunun çok farklı değerler alması faydalı olacaktır. Mesela
cinsiyet sütununa sadece Kadın ve Erkek değerleri girilecek ise bu sütunu
indekslemek bize bir fayda sağlamayacaktır.
 Yabancı Anahtarlar
Tablolarda yer alan yabancı anahtarlar JOIN işlemlerinin nerelerden olacağı
konusunda çok güçlü ipucudurlar. Özellikle çok satırlı tablolarınızı bağlayan
yabancı anahtarlarınızı mutlaka nonclustred indeks ile indeksleyin.
 Sorgu Kapsama
Tamamı hızlanacak sorgular için kapsamlı indeksler tanımlanabilir.
SELECT faturakod, urunkod, adet FROM SiparisDetay
WHERE FaturaKod = 1 AND urunkod = 2627 AND adet = 1
Şeklinde bir sorguyu ele alalım. Tablo üzerinde (faturaKod , urunkod) sütunlarını
içeren bir indeks tanımlandığında sorgu adet sütununu içerdiği için clustered
indeks kullanılmaya devam edecektir. Ancak (faturaKod , urunkod, adet) şeklinde
bir indeks tanımlandığında sorgunun hızı artacaktır.
Sonuç olarak, bir tablo için şu dört durumdan biri geçerlidir;
1 – Tablo heap‟tir. Yani üstünde fiziksel olarak sıralayıcı kural tanımlanmamıştır.
Kayıtlar giriliş sırası ile tutulmaktadır.
2 – Tablo üstünde bir Clustered İndeks tanımlıdır. Bir sütun veya bazen birden fazla
sütunun birleşimi, verilerin sıralanmasında kullanılmıştır.
3 – Tablo üstünde nonclustered indeks tanımlanmıştır ama clustered indeks
bulunmadığı için bu indeks heap yapısı üstünden çalışmaktadır.
4 - Tablo üstünde nonclustered indeks tanımlanmıştır ve clustered indeks üzerinden
çalışmaktadır.
Veritabanı Yönetim Sistemleri Ġndeksleri Ne Zaman Kullanır?
1. Noktasal sorguları hızlandırmak için: WHERE cümleciğinden sonra uygun indeks
bulunursa tabloyu taramak yerine indeks kullanılır.
SELECT * FROM urun WHERE urunkod = 532
Örneğin yukarıdaki cümlede urunkod sütunu clustered indeks olarak tanımlı ise
sonucu kısa bir sürede getirecektir.
2. Aralık tarayan sorguları hızlandırmak için: Değerleri bilinen bir aralıkta olan
sorguları getirirken indekslerden yararlanılabilir. (BETWEEN, LIKE gibi)
SELECT * FROM urun WHERE adi LIKE „Pan%‟
Örneğin yukarıdaki cümlede adi sütunu indekslenmiş ise veritabanı indeks yardımı
ile sonucu kısa bir sürede getirecektir.
3. JOIN işlemlerinde PRIMARY KEY-FOREIGN KEY (birincil anahtar-yabancı
anahtar) eşleşmesi varsa indekslerden yararlanılır. (Nested Join)
4. JOIN işlemlerinde birleşecek sütunlar üzerinde indeks oluşturulmuş ise bu
indekslerden yararlanabilir. (Merge Join)
İndeks bulunmazsa veya Hash Join „in daha verimli olduğu düşünülürse Hash Join
kullanılır.
5. Veritabanı, PRIMARY KEY veya UNIQUE olarak tanımlanan sütunlar için arka
planda unique indeks‟ler kullanır.
6. ORDER BY kullanıldığında verileri belli bir sırada getirmek için indeks
kullanabilir.
SQL Server Ġndeks Türleri
Unique Index
İndeks‟teki verilerin tekrarlayamaması amacıyla kullanabiliriz.
Karma (composite) indeks
Birden fazla sütunu kapsayan indeksler.
Kapsam (covering) indeksler
Bir sorgunun WHERE kısmında seçilen sütunları birlikte tek bir indeks olarak
tanımlanmasına Covering Indeks denir. Covering İndeks genellikle çok I/O işlemi gerektirir
ama sorgunun çok hızlı sonuçlanmasını sağlar. Ancak covering indeks tanımlarken indeksler
arası bölge kavramına (clustered indeks içerisindeki sütunu tekrar indekse dahil etmek
gerekmez) ve sorgulanan sütunlar ile indekslenen sütunların sırasının aynı olmasına dikkat
ederek tanımlanması gerekir.
Parçalı Ġndeksler
Farklı fiziksel dosya gruplarına dağıtılmış indekslere verilen addır. Paralel I/O
performansını arttırır.
XML Ġndeksler
XML sütunlar üzerinde de sorguların hızlanmasını sağlamak üzere indeks
tanımlamamızı sağlar.
Full-Text Ġndeksler
Metin ifadelerinin hızlı sorgulanmaları amacıyla tercih edilirler. Yapıları diğer
indeksle aynı olmasına rağmen birçok yönü ile diğer indekslerden ayrılır.
Full-text indeksler sadece char, nchar, varchar, nvarchar, varbinary, image, ve XML
türünden veri içeren sütunlar üzerinde ve bir tablo için sadece bir tane tanımlanabilirler.
FILLFACTOR ve PAD_INDEX parametrelerine karar vermek
Kayıtlar eklenip silindikçe, indeks sayfalarının doluluk oranı değişecektir. Doluluk
oranının düşmesi okuma işlemlerinin yavaşlamasına neden olur. Bu durum, OLAP için
dezavantajlı iken OLTP için avantajlı olabilir.
Öte yandan çok dolu sayfalar da yazma ve güncelleme açısından sıkıntı doğuracaktır.
Bu durum da OLTP için dezavantajlı iken OLAP için avantajlı olabilir.
Dolayısıyla bir OLTP sistemde, sürekli olarak INSERT, UPDATE ve DELETE
işlemleri olduğundan, indeks sayfalarında boş alanlar bırakarak gitmek daha akıllıca olur.
OLAN sistemler için ise indeks sayfalarının daha dolu olması tercih edilir. Bu işlemler için
FILLFACTOR ve PAD_INDEX parametreleri kullanılır. FILLFACTOR uç seviye sayfaların
ne kadar doluluk oranında olacağını belirtir. PAD_INDEX ise bu oranın uç sayfalar dışındaki
sayfalarda da geçerli olup olmayacağını ifade etmek için kullanılır. PAD_INDEX
kullanılmazsa ara seviye sayfalar için en az 2 indeks sığacak kadar olmak üzere SQL server
tarafından uygun bulunan miktarda boş yer bırakılır.
Doluluk Oranı
FILLFACTOR
Yüzde Oranı
Uç Seviye
Sayfalar
Ara Seviye Sayfalar
(PAD_INDEX yok)
Ara Seviye Sayfalar
(PAD_INDEX)
Kullanım
Yerleri
n (1-99)
% n dolu
2 indekslik boş
% n dolu
OLTP
100
% 100 dolu
2 indekslik boş
% 100 dolu
OLAP
Tablo 1. FILLFACTOR ve PAD_INDEX parametrelerinin indeks sayfalarındaki doluluk oranına etkisi
ĠNDEKS OLUġTURMAK
İndeks oluşturmak için kullanılan SQL ifadesinin en temel kullanım şekli aşağıda
verilmiştir.
CREATE [UNIQUE] indeks-tipi INDEX indeks-ismi ON tablo-ismi ( sütun-ismi )
İndeks-tipi
: CLUSTERED, NONCLUSTERED
Örnek : Personel tablosunu sicil sütununa Clustered İndeks tanımlayalım.
CREATE CLUSTERED INDEX persicil ON
personel ( sicilno )
Örnek : Personel tablosunun adi sütununa NonClustered İndeks tanımlayalım.
CREATE INDEX peradi ON personel ( adi )
UNIQUE INDEKS
Bir unique indeks, indeks olarak kullanılan sütun içerisinde benzer iki veya daha fazla
satıra ve NULL değere izin vermez.
Not : Primary Key Constraint, kullanıcı bir seçenek belirtmezse SQL Server tarafından
Clustred Unique Indeks olarak tanımlanır.
Unique Constraint ise non-clustered unique indeks olarak tanımlanır.
Örnek : Kitap tablosunun ISBN sütununa Unique (tekil) olarak NonClustered İndeks
tanımlayalım.
CREATE UNIQUE INDEX kitap_ISBN ON kitap
( ISBN )
KARMA ĠNDEKS (Birden fazla sütun üzerinde indeks)
İki veya daha fazla sütun üzerinde arama işleminin performansını arttırmak için karma
indeksler kullanılabilir.
CREATE INDEX peradi ON personel ( adi ,
soyadi )
INDEKS SĠLME
Var olan indeksi silmek için DROP INDEX ifadesi kullanılır. Veritabanından indeks
silindiği zaman kapladığı alan da geri iade edilecektir.
DROP INDEX peradi ON personel
FĠLLFACTOR ve PAD_INDEX parametrelerini ayarlamak
CREATE [UNIQUE] indeks-tipi INDEX indeks-ismi
ON tablo-ismi ( sütun-ismi )
WITH (PAD_INDEX= ON | OFF , FILLFACTOR = yüzde_oranı )
Örnek: tblSiparisDetay tablosu üzerinde, %80 doluluk oranında bir indeks tanımlayalım ve
bu indeksin ara seviyelerde de bu şekilde boşluk bırakmasını sağlayalım. Çünkü sistemimizin
sürekli olarak sipariş almasını bekliyoruz.
CREATE CLUSTERED INDEX cl_SiparisDetay
ON tblSiparisDetay ( faturakod )
WITH (PAD_INDEX = ON , FILLFACTOR = 80)
Ġndeksleri Yeniden Derlemek
Bir indeksi silip yenisini oluşturmak suretiyle kapladığı alanı azaltmak ve iç yapısını
(uç ve ara seviye sayfalar) yeniden inşa etmek amacıyla kullanılır.
ALTER INDEX ALL ON tablo_ismi REBUILD ( seçenekler )
Örnek: ALTER INDEX ALL ON tbl_urun REBUILD WITH (FILLFACTOR=80)
Ġndeksleri Yeniden Düzenlemek
İndeks tanımında yer alan FILLFACTOR değerine eşit olarak uç seviye indeks
sayfalarını yeniden yapılandırır.
ALTER INDEX cv_tblUrun ON tblUrun REORGANIZE
Download