MySQL Indexing Rehberi: Performansın Mimarı

# [Rehber:](https://www.mcozcan.com/haber/rehber-vuejs-optimization-7203) MySQL Indexing — Veritabanı Performansının Görünmez Mimarı Bir MySQL verita...

MySQL Indexing Rehberi: Performansın Mimarı

Rehber: MySQL Indexing — Veritabanı Performansının Görünmez Mimarı

Bir MySQL veritabanı, ilk günlerinde ne kadar hızlı olursa olsun, veri hacmi büyüdükçe yavaşlar. Bu yavaşlamanın arkasındaki en yaygın sebep, yanlış veya eksik indekslemedir. Peki indeks nedir, nasıl çalışır ve doğru şekilde nasıl tasarlanır? Bu rehberde MySQL indekslerini hem teorik hem de pratik yönleriyle ele alacağız.

Index Nedir ve Neden Bu Kadar Önemli?

Bir indeks, kitabın sonundaki dizin gibi düşünülebilir. 500 sayfalık bir kitapta "MySQL" kelimesini aramak yerine dizine bakıp ilgili sayfaya atlarsınız. MySQL de aynı mantıkla çalışır: indeks olmadan tüm satırları tek tek tarar (full table scan), indeksle ise doğrudan ilgili veriye ulaşır.

Küçük tablolarda bu fark hissedilmez. Ancak milyonlarca satır söz konusu olduğunda indeksli bir sorgu milisaniyeler içinde dönerken, indekssiz sorgu saniyeler, hatta dakikalar sürebilir.

İndeksin Sağladığı Kazanımlar

  • Hızlı SELECT sorguları: WHERE, JOIN ve ORDER BY işlemlerinde ciddi hız artışı
  • Etkin sıralama: ORDER BY ve GROUP BY operasyonlarının hızlandırılması
  • Tekillik garantisi: UNIQUE indekslerle veri tutarlılığı
  • JOIN performansı: İlişkili tablolar arasında hızlı eşleştirme

İndeksin Maliyeti

Her şeyin bir bedeli olduğu gibi indekslerin de vardır:

  • Disk alanı tüketimi: Her indeks ekstra yer kaplar
  • Yazma yavaşlaması: INSERT, UPDATE, DELETE işlemlerinde indekslerin de güncellenmesi gerekir
  • Bakım yükü: Gereksiz indeksler sorgu optimizasyonunu zorlaştırır

MySQL'de İndeks Türleri

MySQL, ihtiyaca göre farklı indeks türleri sunar. Doğru türü seçmek, performansın anahtarıdır.

1. B-Tree Index (Varsayılan)

Çoğu depolama motorunda (InnoDB, MyISAM) varsayılan indeks türüdür. Dengeli ağaç yapısı kullanır ve eşitlik, aralık, sıralama sorgularında etkilidir.

CREATE INDEX idx_email ON users(email);

2. Hash Index

Yalnızca eşitlik karşılaştırmalarında kullanılır. MEMORY motorunda doğal olarak bulunur, InnoDB'de ise "adaptive hash index" olarak otomatik devreye girer.

3. Full-Text Index

Metin arama için tasarlanmıştır. MATCH ... AGAINST sözdizimiyle kullanılır.

CREATE FULLTEXT INDEX idx_content ON articles(title, body);
SELECT * FROM articles WHERE MATCH(title, body) AGAINST('mysql performans');

4. Spatial Index

Geometrik veri tipleri (POINT, POLYGON) için kullanılır. Harita tabanlı uygulamalarda kritiktir.

5. Composite (Bileşik) Index

Birden fazla sütunu tek indekste birleştirir. Doğru sıralama ile kullanıldığında çok güçlüdür.

CREATE INDEX idx_user_status ON orders(user_id, status, created_at);

İndeks Oluşturma: Temel Sözdizimi

CREATE INDEX ile

CREATE INDEX idx_lastname ON employees(last_name);
CREATE UNIQUE INDEX idx_username ON users(username);

ALTER TABLE ile

ALTER TABLE products ADD INDEX idx_price (price);
ALTER TABLE products ADD UNIQUE INDEX idx_sku (sku);

Tablo Tanımlarken

CREATE TABLE customers (
    id INT PRIMARY KEY AUTO_INCREMENT,
    email VARCHAR(255) NOT NULL,
    city VARCHAR(100),
    created_at DATETIME,
    INDEX idx_city (city),
    UNIQUE INDEX idx_email (email)
);

PRIMARY KEY, UNIQUE ve Normal Index Farkları

Özellik PRIMARY KEY UNIQUE INDEX
Tekillik Zorunlu Zorunlu Yok
NULL değer Kabul etmez Kabul eder (birden fazla) Kabul eder
Tablo başına 1 adet Birden fazla Birden fazla
Kümelenmiş (InnoDB) Evet Hayır Hayır

InnoDB'de PRIMARY KEY kümelenmiş indekstir; yani tablo verisi doğrudan bu indeksin yapraklarında saklanır. Bu yüzden birincil anahtar seçimi kritik önem taşır.

Bileşik İndekslerde Sütun Sırası: En Kritik Detay

Bileşik indekslerde sütun sırası, indeksin kullanılabilirliğini doğrudan etkiler. Sol önek (leftmost prefix) kuralı geçerlidir.

CREATE INDEX idx_a_b_c ON tablo(a, b, c);

Bu indeks şu sorgularda kullanılır:

  • WHERE a = ?
  • WHERE a = ? AND b = ?
  • WHERE a = ? AND b = ? AND c = ?

Ancak şu sorgularda kullanılmaz:

  • WHERE b = ? (a atlanmış)
  • WHERE c = ? (a ve b atlanmış)
  • WHERE b = ? AND c = ?

Bu nedenle indeks tasarlarken en sık kullanılan ve en seçici sütunu en başa koymak gerekir.

Covering Index (Kapsayıcı İndeks)

Bir sorgunun ihtiyaç duyduğu tüm sütunlar indekste mevcutsa, MySQL tabloya hiç dokunmadan yanıt üretebilir. Buna "covering index" denir ve ciddi performans kazancı sağlar.

CREATE INDEX idx_cover ON orders(user_id, status, total);
SELECT user_id, status, total FROM orders WHERE user_id = 5;

Burada sorgu yalnızca indeksten okunur; tablo erişimi olmaz.

EXPLAIN ile İndeks Kullanımını Analiz Etmek

Bir sorgunun indeksi kullanıp kullanmadığını görmek için EXPLAIN komutu hayat kurtarır.

EXPLAIN SELECT * FROM users WHERE email = 'ornek@mail.com';

Çıktıdaki type alanına dikkat edin:

  • const / eq_ref → Mükemmel
  • ref / range → İyi
  • index → Tüm indeks taranıyor
  • ALL → Full table scan, tehlikeli

possible_keys ve key alanları, hangi indeksin aday olduğunu ve hangisinin seçildiğini gösterir. rows alanı ise taranan tahmini satır sayısıdır.

İndekslerin Kullanılmadığı Durumlar

İndeks olsa bile bazı sorgular onu kullanamaz:

  • Sütun üzerinde fonksiyon: WHERE YEAR(created_at) = 2024
  • Baştaki joker karakter: WHERE name LIKE '%ahmet'
  • Tip uyumsuzluğu: WHERE user_id = '5' (sayısal sütuna string)
  • OR koşulları (her iki tarafta indeks yoksa)
  • Düşük kardinalite: WHERE gender = 'E' (neredeyse tüm satırlar aynı)

Çözüm: Fonksiyonu sütundan kaldırın, joker karakteri sona alın, tip uyumunu sağlayın.

İndeks Bakımı ve Optimizasyonu

İndeksler zamanla "şişebilir". Düzenli bakım önemlidir.

İndeks Kullanımını İzleme

SELECT * FROM sys.schema_unused_indexes;
SELECT * FROM sys.schema_redundant_indexes;

Bu görünümler, hiç kullanılmayan veya gereksiz indeksleri tespit etmenizi sağlar.

İndeks İstatistiklerini Güncelleme

ANALYZE TABLE users;

İndeks Silme

DROP INDEX idx_eski ON users;
ALTER TABLE users DROP INDEX idx_eski;

İndeks Yeniden Oluşturma

InnoDB'de OPTIMIZE TABLE indeksleri yeniden düzenler:

OPTIMIZE TABLE orders;

İndeks Tasarımında Altın Kurallar

  1. Az ama öz: Her sütuna indeks eklemek performansı düşürür, artırmaz.
  2. Kardinaliteye dikkat: Yüksek kardinaliteli (çok farklı değer içeren) sütunlar önceliklidir.
  3. Bileşik indekste sıra önemli: En seçici ve en sık sorgulanan sütun başa gelir.
  4. FOREIGN KEY sütunlarını indeksleyin: JOIN performansı için kritik.
  5. WHERE + ORDER BY kombinasyonunu düşünün: İkisini de karşılayan indeks ideal.
  6. Covering index fırsatlarını değerlendirin: SELECT sütunlarını indekse dahil edin.
  7. Kullanılmayan indeksleri temizleyin: Yazma yükünü azaltır.
  8. EXPLAIN alışkanlık haline gelsin: Her kritik sorguyu analiz edin.

Sık Yapılan Hatalar

  • Her sütuna ayrı indeks eklemek (indeks enflasyonu)
  • Bileşik indekste yanlış sıralama yapmak
  • Düşük kardinaliteli sütunları indekslemek
  • Sorgularda sütun üzerinde fonksiyon kullanmak
  • İndekslerin bakımını ihmal etmek
  • Test ortamında veri olmadan indeks kararı vermek

Sonuç

MySQL indeksleme, veritabanı performansının görünmez ama en güçlü mimarıdır. Doğru tasarlanmış birkaç indeks, yüzlerce satır kod optimizasyonundan daha fazla kazanç sağlayabilir. Ancak indeksler sihirli değnek değildir; yanlış kullanıldığında yazma performansını düşürür ve disk alanını israf eder.

Özetle: Sorgularınızı tanıyın, EXPLAIN ile analiz edin, bileşik indekslerde sıralamayı doğru yapın ve kullanılmayan indeksleri temizleyin. Bu disiplinli yaklaşım, veritabanınızın ölçek büyüdükçe de hızlı kalmasını sağlayacaktır.

Unutmayın: En iyi indeks, sorgunuzun gerçekten ihtiyaç duyduğu indekstir — ne bir fazlası, ne bir eksiği.

İLGİLİ İÇERİKLER

Bunları da Okumak İsteyebilirsiniz