Teknik

Sipariş Sayfası 10 Bin Kayıttan Sonra Neden Kilitleniyor? Veritabanı İndekslemenin Kimsenin Anlatmadığı Sıralama Kuralı

Bileşik indeks sırası, kapsayıcı indeks ve filesort tuzağı: e-pin scriptinde sipariş sorgularını saniyelerden milisaniyelere indirmenin teknik yolu.

Sipariş Sayfası 10 Bin Kayıttan Sonra Neden Kilitleniyor? Veritabanı İndekslemenin Kimsenin Anlatmadığı Sıralama Kuralı

İlk bin siparişte her şey uçuyordu. Panel anında açılıyor, filtre anında dönüyordu. Sonra on bini geçtin, rakamlar büyüdü, ve aynı sayfa sekiz saniyede açılmaya başladı. Klasik teşhis şudur: "veri çok, normal." Bu cümle yanlış. On bin satır MySQL için hiçbir şey değildir; milyonlarca satırı milisaniyede döndüren sistemlerden bahsediyoruz. Yavaşlığın sebebi verinin miktarı değil, veritabanının o veriye hangi yoldan gittiğidir.

İndeks, tablonun yanında tutulan sıralı bir yol haritasıdır. Doğru kurulduğunda MySQL aradığı satırlara doğrudan atlar; kurulmadığında tabloyu baştan sona tarar. Ama işin asıl sırrı "indeks ekledim" demek değil: bir e-pin scripti için indeksin hangi kolonları, hangi sırayla içerdiği her şeyi belirler. Yanlış sırada kurulmuş bir bileşik indeks, hiç indeks olmamasıyla neredeyse aynı sonucu verir. Bu yazı o sıralama kuralını ve sipariş sorgularına nasıl uygulanacağını anlatıyor.

8 sn → 40 msDoğru bileşik indeksle tipik sipariş listesi kazancı
%5Üzerinde eşleşme varsa indeks devre dışı bırakılır
3-5Bir tabloda makul indeks sayısı üst sınırı
1Bir sorguda MySQL'in kullandığı indeks sayısı

MySQL indeksi neden bazen görüp de kullanmıyor?

İndeksler B-ağacı yapısında, sıralı biçimde tutulur. Bu yapı iki işi çok iyi yapar: belirli bir değere atlamak ve o değerden sonrasını sıralı biçimde okumak. Ama optimizasyon motoru maliyet hesabı yapar: eğer tahminine göre sorgu tablonun büyük bir bölümünü döndürecekse, indeksten satır satır tabloya gidip gelmek yerine tabloyu doğrudan taramayı tercih eder. Bu bir hata değil, bilinçli bir karardır.

Bu yüzden seçicilik kavramı kritiktir. Sipariş durumu kolonunda yalnızca dört farklı değer varsa ve kayıtların yarısı "tamamlandı" ise, tek başına o kolona koyduğun indeks çoğu sorguda işe yaramaz. Buna karşılık sipariş numarası, müşteri kimliği veya e-posta gibi neredeyse tekil kolonlar yüksek seçiciliktedir ve indeksten en çok faydayı orada görürsün. Düşük seçicilikli kolonlar tek başına değil, bileşik indeksin içinde anlam kazanır.

Bileşik indekste sıra neden pazarlık konusu değil?

Bileşik indeks, telefon rehberi gibi çalışır: soyada göre, sonra ada göre sıralanmıştır. Soyadını bilirsen çok hızlı bulursun. Ama yalnızca adı biliyorsan rehber sana hiç yardım etmez, baştan sona okumak zorunda kalırsın. MySQL'in kuralı da tam budur: bir bileşik indeks ancak en soldaki kolondan başlayarak kullanılabilir.

Pratik karşılığı şu: tipik sipariş sorgun belirli bir müşterinin son siparişlerini tarihe göre tersten listeliyorsa, doğru indeks müşteri kimliği ve tarih kolonlarını bu sırayla içerir. Tersine kurarsan, yani tarih başa gelirse, müşteri filtresi indeksin dışında kalır. Sıralama mantığı da aynı ilkeye tabidir: eşitlikle filtrelediğin kolonlar başa, aralıkla filtrelediğin veya sıraladığın kolonlar sona gelir. Bu kuralı bilen bir dijital ürün satış yazılımı, indeks tasarımını şema kurulurken yapar, sonradan yama atmaz.

Sipariş sorgusu deseniYanlış yaklaşımDoğru indeksTipik kazanç
Bir müşterinin siparişleri, tarihe göre terstenYalnızca tarih kolonunda indeks(müşteri_id, olusturma_tarihi) bileşik50-100 kat
Bekleyen siparişleri kuyruğa almaİndekssiz tam tarama(durum, olusturma_tarihi) bileşik20-60 kat
Sipariş numarasıyla tek kayıt aramaLIKE ile joker aramaSipariş numarasında tekil indeks100 kat üzeri
Belirli ürünün satılmış kodlarıÜrün ve durum ayrı indekslerde(urun_id, durum) bileşik15-40 kat
Aylık ciro özetiTarih kolonuna fonksiyon uygulamakTarih aralığı karşılaştırması + tarih indeksi10-30 kat

Kapsayıcı indeks: tabloya hiç uğramadan cevap vermek

InnoDB'de ikincil indeks, birincil anahtarın değerini taşır. Yani indeksten bulduğun her satır için MySQL bir kez daha birincil anahtar üzerinden tabloya gider. Binlerce satırda bu gidiş-gelişler toplanır. Eğer sorgunun ihtiyaç duyduğu tüm kolonlar indeksin içinde varsa, MySQL tabloya hiç uğramaz ve cevabı doğrudan indeksten üretir. Buna kapsayıcı indeks denir ve sorgu planında "yalnızca indeks kullanıldı" ibaresiyle görünür.

Sipariş listeleme ekranı bunun için biçilmiş kaftandır: genellikle sipariş numarası, tarih, durum ve tutar gösterilir. Bu dört kolonu doğru sırayla tek bir indekste toplarsan liste ekranı tabloya dokunmadan dönmeye başlar. Buradaki tek disiplin, sorguda SELECT * kullanmayı bırakmaktır; yıldız yazdığın anda kapsayıcılık ihtimalini kendi elinle yok edersin. İyi yazılmış bir e-pin satış scripti liste ekranlarında yalnızca gösterdiği kolonları çeker.

İndeksleme sonrası toplam sorgu süresindeki kazancın dağılımı

  • Sipariş listeleme ve filtreleme 45%
  • Kod havuzu ve stok sorguları 25%
  • Panel özet raporları 20%
  • Ödeme bildirimi eşleştirme 10%

Sıralama neden en pahalı adımdır ve nasıl bedava hale gelir?

Sipariş ekranları neredeyse her zaman "en yeni üstte" mantığıyla çalışır. Eğer sıraladığın kolon indeksin uygun pozisyonunda değilse MySQL sonucu bellekte veya diskte ayrıca sıralamak zorunda kalır. Sorgu planında bu iş "ek sıralama gerekti" notuyla belirir ve genellikle sorgunun en pahalı kısmıdır; çünkü sıralama, sayfalama LIMIT'inden önce yapılır.

İşte kritik detay: sayfalamayla birleştiğinde bu durum katlanır. Beş yüzüncü sayfayı isteyen bir sorgu, önündeki bütün satırları okuyup atmak zorundadır; sayfa numarası büyüdükçe sorgu yavaşlar. İki çözüm var: sıralama kolonunu bileşik indeksin sonuna doğru yerleştirmek ve derin sayfalamayı "son görülen kimlikten sonrasını getir" mantığıyla değiştirmek. İkincisi mimari bir karardır ama büyüyen bir e-pin yazılımı için kaçınılmazdır.

Filtrelediğin kolona asla fonksiyon uygulama

Tarih kolonunu bir fonksiyonla sarıp karşılaştırdığın anda indeks devre dışı kalır. Bunun yerine tarih aralığı ile karşılaştır; indeks yeniden devreye girer.

Her şeye indeks koymanın bedeli nedir?

İndeks okumayı hızlandırır, yazmayı yavaşlatır. Her yeni sipariş kaydında MySQL tablonun yanı sıra o tablodaki bütün indeksleri de güncellemek zorundadır. On beş indeksli bir sipariş tablosunda kampanya gününde gelen yoğun yazma trafiği, okuma kazancını fazlasıyla geri alır. Ayrıca indeksler disk ve bellek tüketir; hepsi birden sığmazsa bellek verimi düşer.

İkinci tuzak gereksiz indeks. Elinde müşteri kimliği ve tarihi içeren bileşik bir indeks varsa, yalnızca müşteri kimliğinden oluşan ayrı bir indekse ihtiyacın yoktur; soldan ek kuralı sayesinde bileşik indeks o işi zaten yapar. Düzenli olarak kullanılmayan indeksleri tespit edip temizlemek, yeni indeks eklemek kadar değerlidir. Kural basit: indeksi sorguna göre kur, tahminine göre değil.

Kontrol adımıNasıl doğrulanırHedef
En pahalı sorgu desenlerini çıkarYavaş sorgu kayıtlarını toplam süreye göre sıralaİlk 5 desen belirlendi
Sorgu planını okuErişim tipi ve kullanılan anahtar sütunlarına bakTam tarama kalmadı
Bileşik indeks sırasını doğrulaEşitlik kolonları solda, sıralama kolonu sağdaİndeks tam kullanılıyor
Kapsayıcılığı hedefleListe ekranında yıldız yerine kolon adı yazYalnızca indeksten cevap
Ek sıralamayı yok etPlanda sıralama uyarısı kalmadıSayfalama sabit hızda
Kullanılmayan indeksleri ayıklaİndeks kullanım istatistiklerini inceleGereksiz indeks kaldırıldı
Yazma maliyetini ölçYoğun saatte ekleme süresini karşılaştırYazma süresi kabul sınırında

Şeması büyümeye göre kurgulanmış bir altyapı

Pinova, e-pin ve dijital ürün satan işletmeler için lisanslı bir satış yönetim yazılımıdır; sipariş, kod havuzu ve rapor tabloları artan hacim düşünülerek tasarlanır.

Kaç indeks fazla sayılır?

Kesin bir sayı yok ama yoğun yazma alan sipariş tablolarında 3-5 iyi tasarlanmış indeks çoğu ihtiyacı karşılar. Ondan fazlaysa, indekslerin gerçekten kullanıldığını istatistiklerle doğrulaman gerekir.

Canlı sistemde indeks eklemek tabloyu kilitler mi?

Güncel InnoDB sürümlerinde çoğu indeks ekleme çalışırken yapılabilir, ama büyük tablolarda yük yaratır ve disk alanı ister. Yine de yoğun olmayan bir saatte ve yedek aldıktan sonra yapılır.

Metin içinde arama yapan sorgular için indeks işe yarar mı?

Başında joker karakter bulunan bir arama normal indeksi kullanamaz. Bu tür ihtiyaçlarda ya öneke dayalı arama yapılır ya da tam metin arama yapısı kurulur.

Birincil anahtar olarak rastgele üretilmiş kimlikler kullanmam sorun mu?

InnoDB'de tablo birincil anahtara göre fiziksel olarak sıralı tutulur. Rastgele değerler ekleme sırasında sayfa bölünmesine yol açar ve yazma performansını düşürür. Artan bir sayısal anahtar tutup rastgele kimliği ikincil tekil indekste tutmak daha sağlıklıdır.

İndeksleme, satış hacmi büyüdükçe faturaya değil mimariye yapılan bir yatırımdır: aynı sunucuda on kat fazla siparişi taşımanı sağlar. Kendi kurulumunda sipariş ekranlarının ve rapor sayfalarının kalabalık veriyle nasıl davrandığını görmek istersen özellikler bölümünü incele, fiyat seçeneklerini karşılaştır ve canlı demo üzerinden filtreleri, sayfalamayı ve panel özetlerini bizzat deneyerek farkı hisset.

Daha Fazlasını Keşfedin

Dijital ürün satışı ve otomasyon üzerine güncel rehberlere göz atın.

Tüm Yazıları Gör →
Bu yazıyı paylaşın
Bu yazıyı beğendiniz mi?
Teşekkürler!
← Tüm yazılar