CodeWriteson
SELECT * FROM tools WHERE name="Laravel";
şeklinde bir sorgunuz olduğunu düşünün. Bu tabloda eğer 999999999 kayıt varsa veritabanı motoru bu kayda ulaşmak için tüm tabloyu tarar. Tüm tablonun taranması için harcanan süre ile kayıt sayısı doğru orantılıdır. Kayıt sayısı arttıkça süre artar. Bunu engellemek için indeksleme kullanılır. Bir kayda indeks oluşturduğunuzda ayrı bir yerde o kaydın değeri ve kaydın bulunduğu yerin işaretçisi tutulur. Aşağıdaki resme bakalım:
Her sayfada sağdaki harfli fihristteki harflerle başlayan kelimelerin kayıtlı olduğunu düşünün. Ben size Laravel kelimesini bulun desem siz ilk sayfadan başlayıp tek tek sayfaları kontrol etmezsiniz değil mi. Direkt fihristten KL bölümüne gelirsiniz ve o sayfayı açıp bakarsınız. Bunu DB olarak düşünün ve bir yerde Laravel → KL
şeklinde ayrı bir kaydın (yani indeks) daha tutulduğunu düşünün. Ben Laravel şeklinde arama yaptığım zaman indeks varsa indekste arama yapıyorum ve sonuç bana KL bölümüne bak şeklinde dönüyor ve ben direkt oraya bakıyorum. Burada Laravel değer, KL ise işaretçi oluyor. (Sonuçta yine bir arama yapılıyor ama indekslerde yapılan elbette tabloda yapılan aramadan kat ve kat daha hızlı.). Ben buradan şunu çıkarıyorum: "Eğer Laravel kelimesini hızlı bulmak istiyorsam onu tutan alan için bir indeks oluşturmalıyım". Bu oluşturacağımız indekse tekil indeks denir. Bunu MySQL'de şöyle oluşturursunuz:
CREATE INDEX {indeks_adi} ON tools (name);
Burada index_adi sizin vereceğiniz bir şey. Örneğin ind_name gibi.
Şimdi ise şöyle bir sorgunuz olduğunu düşünün.
SELECT * FROM tools WHERE name="Laravel" AND language="PHP" AND description="Framework";
Burada işin rengi değişti çünkü bu sefer aramanıza language ve description alanı da eklediniz. Sizin ilk eklediğiniz indeksin burada pek bir etkisi olmayacak çünkü ekstra bir şart için de tarama gerekiyor. Bunu engellemek için ise neyi nasıl arayacaksanız ona göre indeks oluşturmanız lazım. Bu sefer 3 alanını kapsayan bir indeks oluşturmanız lazım. Buna da çoklu indeks denir, multi-column ya da composite index şeklinde geçer:
CREATE INDEX {indeks_adi} ON tools (name, language, description);
Burada artık üstte oluşturduğunuz tekil indeksi oluşturmanıza gerek yok çünkü bu tarz bir indekste şu şekilde indeksleme otomatik oluşur:
name
name, language
name, language, description
Yani aşağıdaki 3 sorgu da indeksleme kullanarak hızlı bir şekilde kayıtları getirir:
SELECT * FROM tools WHERE name="Laravel";
SELECT * FROM tools WHERE name="Laravel" AND language="PHP";
SELECT * FROM tools WHERE name="Laravel" AND language="PHP" AND description="Framework";
Burada sıra ve aralık önemlidir. Aşağıdaki sorgular indeksten faydalanmaz ve tüm tabloyu tarar:
SELECT * FROM tools WHERE name="Laravel" AND description="Framework";
SELECT * FROM tools WHERE description="Framework" AND language="PHP";
SELECT * FROM tools WHERE description="Framework";
SELECT * FROM tools WHERE language="PHP" AND name="Laravel" AND description="Framework";
Kayıtlarınıza eklediğiniz PRIMARY KEY otomatik olarak kendi için indeks oluşturduğu için id=5 şeklinde yaptığınız sorgular da hızlı çalışır. O yüzden PRIMARY KEY için ayrıca indeks oluşturulmaz.
Eğer bir ya da birden fazla alanın bir tabloda sadece bir kere yer almasını yani benzersiz (unique) olmasını isterseniz o alan için benzersiz indeks oluşturursunuz. Tekil ya da çoklu olabilir:
CREATE UNIQUE INDEX {indeks_adi} ON tools (name);
CREATE UNIQUE INDEX {indeks_adi} ON tools (name, language);
Örneğin ikinci örnekteki gibi bir indeks oluşturduğunuzda tools tablosuna iki kez name="Laravel" ve language="PHP" olacak şekilde kayıt giremezsiniz. Bu kaydı ekledikten sonra name="Symfony" ve language="PHP" şeklinde bir kayıt ekleyebilirsiniz.
Indeksler de yer kaplar o yüzden mantıklı indeksleme yapmanız gerekiyor yoksa tablonun (ya da indekslerin) kapladığı fiziksel alan artar, alan ve performans problemleri yaşarsınız. O yüzden bazen string ifade içeren alanlar indekslenecekse VARCHAR vs değil de BINARY olarak belirlenir.
Foreign key oluşturduğunuzda da otomatik indeks eklenir, o yüzden foreign key eklediğinizde indeks eklemenize gerek yok.
Full-text indeks eklediğinizde CHAR, VARCHAR, TEXT gibi alanlarda LIKE'a göre çok daha performanslı aramalar yapabilirsiniz ve kayıtları da en alakalı kayıtlar en üstte olacak şekilde sıralayabiliriniz. Full-text indeks sadece CHAR, VARCHAR, TEXT, LONGTEXT... şeklindeki alanlara oluşturulabilir.
Ayrıca indeksler btree ve hash tiplerinde olabiliyor fakat foreign key, full-text indeks ve bu indeks tiplerinin açıklamaları kolay dille anlatılan şeyler değil. Bunları araştırmak size kalıyor.
Son olarak sonuçta burası Laravel forumları olduğu için Laravel içerisinde indeksleme nasıl yapılıyor derseniz:
https://laravel.com/docs/7.x/migrations#indexes