Bilmeniz gereken ilk şey, indekslerin aradığınız sonucu elde etmek için tam tabloyu taramaktan kaçınmanın bir yolu olduğudur.
Farklı türde dizinler vardır ve bunlar depolama katmanında uygulanır, bu nedenle aralarında standart yoktur ve kullandığınız depolama motoruna da bağlıdır.
InnoDB ve B + Tree dizini
InnoDB için, en yaygın dizin türü, öğeleri sıralı bir sırada depolayan B + Ağaç tabanlı dizindir. Ayrıca, dizine alınan değerleri almak için gerçek tabloya erişmeniz gerekmez, bu da sorgunuzun daha hızlı dönmesini sağlar.
Bu dizin türüyle ilgili "sorun", dizini kullanmak için en soldaki değeri sorgulamanız gerektiğidir. Dolayısıyla, dizininizde last_name ve first_name olmak üzere iki sütun varsa, bu alanları sorgulama sırası çok önemlidir .
Yani, aşağıdaki tablo verildiğinde:
CREATE TABLE person (
last_name VARCHAR(50) NOT NULL,
first_name VARCHAR(50) NOT NULL,
INDEX (last_name, first_name)
);
Bu sorgu dizinden yararlanır:
SELECT last_name, first_name FROM person
WHERE last_name = "John" AND first_name LIKE "J%"
Ama bir sonraki
SELECT last_name, first_name FROM person WHERE first_name = "Constantine"
Çünkü önce first_name
sütunu sorguluyorsunuz ve bu dizinde en soldaki sütun değil.
Bu son örnek daha da kötü:
SELECT last_name, first_name FROM person WHERE first_name LIKE "%Constantine"
Çünkü şimdi, dizindeki en sağdaki alanın en sağ kısmını karşılaştırıyorsunuz.
Karma dizini
Bu, maalesef, yalnızca bellek arka ucunun desteklediği farklı bir dizin türüdür. Şimşek hızındadır, ancak yalnızca tam aramalar için kullanışlıdır, yani >
, <
veya gibi işlemler için kullanamazsınız LIKE
.
Yalnızca bellek arka ucu için çalıştığından, muhtemelen çok sık kullanmazsınız. Şu anda düşünebildiğim ana durum, başka bir seçimden bir dizi sonuç ile bellekte geçici bir tablo oluşturduğunuz ve karma dizinleri kullanarak bu geçici tabloda çok sayıda başka seçim gerçekleştirdiğiniz durumdur.
Büyük bir VARCHAR
alanınız varsa, B-Ağacı kullanırken, başka bir sütun oluşturarak ve büyük değerin bir karmasını üzerine kaydederek bir karma dizininin kullanımını "taklit edebilirsiniz". Diyelim ki bir URL'yi bir alanda saklıyorsunuz ve değerler oldukça büyük. Ayrıca, adlı bir tamsayı alanı oluşturabilir ve URL'yi eklerken hash yapmak için url_hash
benzeri bir hash işlevi CRC32
veya başka bir hash işlevi kullanabilirsiniz. Ve sonra, bu değeri sorgulamanız gerektiğinde, böyle bir şey yapabilirsiniz:
SELECT url FROM url_table WHERE url_hash=CRC32("http://gnu.org");
Yukarıdaki örnekle ilgili sorun, CRC32
işlev oldukça küçük bir karma oluşturduğundan, karma değerlerinde çok sayıda çarpışma ile sonuçlanmanızdır. Kesin değerlere ihtiyacınız varsa, aşağıdakileri yaparak bu sorunu çözebilirsiniz:
SELECT url FROM url_table
WHERE url_hash=CRC32("http://gnu.org") AND url="http://gnu.org";
Çarpışma sayısı yüksek olsa bile hala hash yapmaya değer, çünkü tekrarlanan karmalarla sadece ikinci karşılaştırmayı (dize) gerçekleştireceksiniz.
Ne yazık ki, bu tekniği kullanarak, url
alanı karşılaştırmak için yine de masaya vurmanız gerekir .
Sarmak
Optimizasyon hakkında her konuşmak istediğinizde dikkate alabileceğiniz bazı gerçekler:
Tamsayı karşılaştırma, dize karşılaştırmasından çok daha hızlıdır. İçindeki karma indeksinin emülasyonu ile ilgili örnek ile açıklanabilir InnoDB
.
Belki de bir sürece ek adımlar eklemek işlemi daha hızlı değil, daha hızlı hale getirir. Bu, SELECT
a'yı iki adıma bölerek, ilk olarak yeni oluşturulan bir bellek içi tabloda değerler depolayarak ve daha sonra bu ikinci tabloda daha ağır sorguları yürüterek optimize edebileceğiniz gerçeğiyle açıklanabilir.
MySQL'in başka dizinleri de var, ama b + ağacı bir şimdiye kadar en çok kullanılan ve karma bir bilmek iyi bir şey olduğunu düşünüyorum, ancak MySQL belgelerinde diğerlerini bulabilirsiniz .
"Yüksek Performanslı MySQL" kitabını okumanızı tavsiye ederim, yukarıdaki cevap kesinlikle indekslerle ilgili bölümüne dayanıyordu.