
Veritabanı İndeks Optimizasyonu: Yavaş Sorguları Hızlandırma
B-Tree, Hash, GIN, GIST indeks türleri, EXPLAIN ile sorgu planı analizi ve slow query log kullanımı. MySQL, MariaDB ve PostgreSQL için composite, covering ve partial indeks stratejileri.
Veritabanı İndeks Optimizasyonu: Yavaş Sorguları Hızlandırma
Bir milyon satırlık tablo var, sorgu 4 saniyede dönüyor. Sunucuya daha fazla RAM eklediniz, yine yavaş. Büyük ihtimalle sorun donanımda değil — eksik ya da yanlış bir indeks yüzünden veritabanı her sorguda tüm tabloyu baştan sona tarıyor. Bu yazıda indeks türlerini (B-Tree, Hash, Bitmap, GIN, GIST), EXPLAIN ile sorgu planı okumayı ve slow query log analizini gerçek kod örnekleriyle anlatıyoruz.
Buyukweb perspektifi: cPanel paylaşımlı hosting paketlerimizde MariaDB 10.6 LTS standart kuruludur. VDS sunucularda root yetkisiyle
slow_query_log,EXPLAIN ANALYZEve pt-query-digest tam kullanılabilir. Daha ileri indeks optimizasyonu için VDS altyapısı şarttır — destek için 0850 302 60 70.
İndeks Neden Hızlandırır: Full Table Scan vs B-Tree Lookup
İndeks olmayan bir tabloda WHERE musteri_id = 1234 sorgusu yazdığınızda veritabanı her satırı sırayla kontrol eder. Bu O(n) karmaşıklığı anlamına gelir: 1 milyon satırlık tabloda ortalama 500.000 satıra dokunulur.
B-Tree indeksi ile aynı sorgu O(log n) ile çalışır: 1 milyon satır için sadece ~20 adımda hedef değer bulunur. Sayısal fark somuttur:
Tablo: 1.000.000 satır, musteri_id sütunu
Full Table Scan → ~500.000 satır kontrol → ~450 ms
B-Tree Index Seek → ~20 node geçişi → ~0.3 ms
İndeks, verinin kopyasını sıralı düzende ayrı bir veri yapısında tutar. INSERT/UPDATE/DELETE her yazma işleminde bu kopya da güncellenir — bu yüzden gereksiz indeks yazma yavaşlığı yaratır.
İndeks Türleri: B-Tree, Hash, Bitmap, FULLTEXT, GIN, GIST, Spatial
B-Tree (Balanced Tree) — Evrensel Varsayılan
MySQL InnoDB ve PostgreSQL'in varsayılan indeks türü. Dengeli ağaç yapısında verileri sıralı tutar.
Desteklediği sorgu tipleri:
- Eşitlik:
WHERE x = 5 - Aralık:
WHERE x BETWEEN 10 AND 50,WHERE x > 100 - Önek:
WHERE ad LIKE 'Ali%' - Sıralama:
ORDER BY x
-- MySQL / MariaDB
CREATE INDEX idx_musteri_id ON siparisler(musteri_id);
-- PostgreSQL (varsayılan B-Tree)
CREATE INDEX idx_musteri_id ON siparisler(musteri_id);
CREATE INDEX idx_musteri_id ON siparisler USING BTREE(musteri_id); -- açık yazım
Hash İndeks — O(1) Eşitlik, Aralık Yok
Hash fonksiyonu değeri doğrudan bellek adresine eşler. Yalnızca = operatörü için kullanılır; >, <, BETWEEN veya ORDER BY için işe yaramaz.
MySQL MEMORY engine hariç Hash indeks desteklemez (InnoDB'de adaptif hash dahili kullanım içindir, manuel oluşturulmaz). PostgreSQL'de açıkça oluşturulabilir:
-- PostgreSQL — sadece eşitlik sorguları için
CREATE INDEX idx_hash_email ON kullanicilar USING HASH(email);
-- SELECT * FROM kullanicilar WHERE email = '[email protected]' → hash hit, çok hızlı
-- SELECT * FROM kullanicilar WHERE email > '[email protected]' → hash çalışmaz, seq scan
Bitmap İndeks — Düşük Kardinalite, AND/OR Kombinasyonu
Bitmap indeks, her benzersiz değer için bir bit dizisi (bitmap) oluşturur. durum = 'aktif' için milyonlarca satırın her biri tek bit ile temsil edilir. AND/OR sorguları iki bitmap'i bit-level AND/OR işlemiyle birleştirir — son derece hızlı.
Uygun alan: Kardinalitesi düşük sütunlar — cinsiyet (E/K), sipariş durumu (3-5 değer), boolean flag.
PostgreSQL'de bitmap indeks yoktur; optimizer sorgu sırasında otomatik olarak bitmap heap scan uygular (mevcut indekslerden geçici bitmap oluşturur). MySQL ve MariaDB bitmap indeksi desteklemez.
-- PostgreSQL: iki ayrı B-Tree index varsa optimizer otomatik bitmap OR scan yapar
CREATE INDEX idx_durum ON siparisler(durum);
CREATE INDEX idx_kategori ON siparisler(kategori_id);
-- WHERE durum = 'aktif' OR kategori_id = 5 → Bitmap OR
-- WHERE durum = 'aktif' AND kategori_id = 5 → Bitmap AND
FULLTEXT İndeks — Doğal Dil Araması
Metin içinde kelime bazlı arama için. Standart B-Tree ile LIKE '%kelime%' çalışmaz — FULLTEXT bu durumu çözer.
-- MySQL / MariaDB
CREATE FULLTEXT INDEX idx_ft_urun ON urunler(ad, aciklama);
SELECT * FROM urunler
WHERE MATCH(ad, aciklama) AGAINST('laptop güç' IN BOOLEAN MODE);
-- PostgreSQL tsvector ile
CREATE INDEX idx_ts_urun ON urunler USING GIN(to_tsvector('turkish', aciklama));
SELECT * FROM urunler
WHERE to_tsvector('turkish', aciklama) @@ to_tsquery('turkish', 'laptop');
GIN — Generalized Inverted Index (PostgreSQL)
GIN, bir değerin içindeki elemanları indeksler: dizilerin her öğesi, JSONB'nin her anahtar/değer çifti, tam metin aramasının her kelimesi ayrı ayrı indekslenir.
-- JSONB alanını tam indeksle
CREATE INDEX idx_gin_meta ON urunler USING GIN(meta_data);
SELECT * FROM urunler WHERE meta_data @> '{"renk": "kirmizi"}';
-- Dizi alanı
CREATE INDEX idx_gin_etiketler ON icerik USING GIN(etiketler);
SELECT * FROM icerik WHERE etiketler @> ARRAY['seo', 'hosting'];
-- pg_trgm ile LIKE '%...%' desteği
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE INDEX idx_gin_trgm ON urunler USING GIN(ad gin_trgm_ops);
SELECT * FROM urunler WHERE ad ILIKE '%laptop%'; -- indeks kullanır!
GIN yazma maliyeti B-Tree'den yüksektir ama JSONB/dizi aramaları için rakipsizdir. PostgreSQL'e özgüdür.
GIST — Generalized Search Tree (PostgreSQL)
GIST, B-Tree'nin genelleştirilmiş halidir. Geometrik veri, tam metin, aralık tipleri için kullanılır.
-- Geometrik nokta araması (PostGIS olmadan)
CREATE INDEX idx_gist_konum ON magazalar USING GIST(konum);
SELECT * FROM magazalar WHERE konum <-> POINT(29.0, 41.0) < 10;
-- Tarih aralığı örtüşme (range type)
CREATE INDEX idx_gist_rezervasyon ON rezervasyonlar USING GIST(tarih_aralik);
SELECT * FROM rezervasyonlar WHERE tarih_aralik && '[2026-06-01, 2026-06-07)';
Spatial (R-Tree) İndeks — Coğrafi Veriler
MySQL ve MariaDB'de coğrafi veri için R-Tree tabanlı SPATIAL INDEX kullanılır; PostgreSQL'de PostGIS + GIST tercih edilir.
-- MySQL / MariaDB
ALTER TABLE magazalar ADD SPATIAL INDEX idx_sp_konum(konum);
SELECT * FROM magazalar
WHERE ST_Contains(ST_Buffer(ST_GeomFromText('POINT(29.0 41.0)'), 0.1), konum);
Composite (Çok Sütunlu) İndeks ve Leftmost Prefix Kuralı
Bileşik indeks birden fazla sütunu tek indekste birleştirir.
CREATE INDEX idx_composite ON siparisler(musteri_id, durum, tarih);
Leftmost prefix kuralı: Optimizer bu indeksi yalnızca en soldaki sütundan başlayan WHERE kombinasyonlarında kullanır.
| WHERE Koşulu | İndeks Kullanımı |
|---|---|
WHERE musteri_id = 1 |
Kullanır (ilk sütun) |
WHERE musteri_id = 1 AND durum = 'aktif' |
Kullanır (ilk + ikinci) |
WHERE musteri_id = 1 AND durum = 'aktif' AND tarih > '2026-01-01' |
Kullanır (tüm sütunlar) |
WHERE durum = 'aktif' |
Kullanmaz (ilk sütun atlanmış) |
WHERE tarih > '2026-01-01' |
Kullanmaz (ilk sütun atlanmış) |
WHERE musteri_id = 1 AND tarih > '2026-01-01' |
Kısmen kullanır (ilk sütun + üçüncü sütun için sekans durur) |
Sütun sırası önemlidir. Genel kural: önce eşitlik koşulunda kullanılan sütunlar (kardinalitesi yüksek olanlar önce), sonra aralık/sıralama sütunları.
-- Kötü: durum düşük kardinalite (3-4 değer) → ilk sırada verimsiz
CREATE INDEX idx_yanlis ON siparisler(durum, musteri_id, tarih);
-- İyi: musteri_id yüksek kardinalite → ilk sırada
CREATE INDEX idx_dogru ON siparisler(musteri_id, durum, tarih);
Covering Index — Tabloya Dokunmadan Sonuç
SELECT sorgusunda ihtiyaç duyulan tüm sütunlar indeksin içindeyse veritabanı asıl tabloya hiç gitmez. MySQL buna "Using index" (EXPLAIN Extra sütunu), PostgreSQL "Index Only Scan" der.
-- Hedef sorgu
SELECT musteri_id, durum, tarih FROM siparisler
WHERE musteri_id = 1234 AND durum = 'tamamlandi';
-- Covering index: SELECT'teki tüm sütunlar + WHERE sütunları indekste
CREATE INDEX idx_cover ON siparisler(musteri_id, durum, tarih);
-- EXPLAIN Extra → "Using index" (tablo erişimi yok)
SELECT * kullanımı covering index'i imkânsız kılar — sadece gereken sütunları seçin.
EXPLAIN ile Sorgu Planı Analizi
Her yavaş sorgunun önüne EXPLAIN ekleyin:
EXPLAIN SELECT * FROM siparisler
WHERE musteri_id = 1234
AND durum = 'beklemede'
ORDER BY tarih DESC;
type sütunu — en iyiden kötüye:
| type | Anlam |
|---|---|
system / const |
Tek satır, sabit — en iyi |
eq_ref |
PRIMARY/UNIQUE join — çok iyi |
ref |
Non-unique indeks eşleşmesi — iyi |
range |
İndeks aralık taraması (BETWEEN, >, <) — kabul edilebilir |
index |
Tüm indeks taranıyor — yavaş |
ALL |
Full table scan — kötü, indeks eklenecek |
Diğer kritik sütunlar:
| Sütun | Dikkat |
|---|---|
key: NULL |
Hiç indeks kullanılmamış |
rows: 500000 |
Tahmini taranan satır — yüksekse sorun var |
Extra: Using filesort |
Sıralama indeks dışı yapılıyor |
Extra: Using temporary |
Geçici tablo — ciddi kaynak tüketimi |
Extra: Using index |
Covering index aktif — en verimli |
Örnek kötü çıktı ve düzeltme:
-- EXPLAIN çıktısı: type=ALL, rows=980000, key=NULL → tam tablo taraması
EXPLAIN SELECT id, tutar FROM siparisler
WHERE musteri_id = 1234 AND durum = 'beklemede';
-- Çözüm: composite + covering index
CREATE INDEX idx_ms_durum_tutar ON siparisler(musteri_id, durum, id, tutar);
-- EXPLAIN çıktısı: type=ref, rows=12, Extra=Using index ✓
EXPLAIN ANALYZE (PostgreSQL) / EXPLAIN FORMAT=JSON (MySQL)
Standart EXPLAIN tahmini değerleri gösterir. Gerçek çalışma süresi için:
-- PostgreSQL: gerçek çalışma süresi + buffer istatistikleri
EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT)
SELECT * FROM siparisler
WHERE musteri_id = 1234 AND durum = 'beklemede';
-- Çıktı örneği:
-- Index Scan using idx_musteri_durum on siparisler
-- (cost=0.43..8.45 rows=12 width=156)
-- (actual time=0.021..0.089 rows=12 loops=1)
-- Index Cond: ((musteri_id = 1234) AND (durum = 'beklemede'))
-- Planning Time: 0.3 ms
-- Execution Time: 0.1 ms
-- MySQL 8.0 / MariaDB 10.9+
EXPLAIN ANALYZE SELECT ...;
-- MySQL: JSON format (daha detaylı maliyet bilgisi)
EXPLAIN FORMAT=JSON SELECT ...;
Plan ile gerçek arasında büyük fark varsa istatistikler eskidir — ANALYZE TABLE tablo (MySQL) ya da ANALYZE tablo (PostgreSQL) çalıştırın.
Slow Query Log — Suçlu Sorguyu Bulma
MySQL / MariaDB — Konfigürasyon
# /etc/mysql/mariadb.conf.d/50-server.cnf veya /etc/my.cnf
[mysqld]
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1 # 1 saniyeden uzun sorguları logla
log_queries_not_using_indexes = 1 # indekssiz sorguları da logla
VDS'de restart gerektirmeden anlık aktif etme:
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1.0;
SET GLOBAL log_queries_not_using_indexes = 'ON';
Log Analizi: mysqldumpslow ve pt-query-digest
# En uzun süren 10 sorgu
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log
# En çok tekrarlanan 10 sorgu
mysqldumpslow -s c -t 10 /var/log/mysql/slow.log
pt-query-digest daha ayrıntılı rapor üretir: query fingerprint, yüzdelik istatistikler, zaman dilimine göre filtreleme.
# AlmaLinux / RHEL
yum install percona-toolkit -y
# Ubuntu / Debian
apt install percona-toolkit -y
# Son 3 saatin yavaş sorgularını analiz et
pt-query-digest /var/log/mysql/slow.log --since 3h | head -200
Çıktıda Query_time: 4.2 ve Rows_examined: 490000 görüyorsanız — bu sorgu her çalışmada 490.000 satıra dokunuyor. Tek bir composite indeks bu sayıyı birkaç düzineye düşürebilir.
Buyukweb cPanel notu: Paylaşımlı hosting'de
SET GLOBALyetkisi yoktur. phpMyAdmin > Status sekmesindenSlow_queriessayacını izleyebilirsiniz. Slow query log açılması için destek hattımızı arayın: 0850 302 60 70.
İndeks Eklenmemesi Gereken Durumlar
Her sütuna indeks eklemek mantıklı değildir:
1. Çok düşük kardinalite: cinsiyet (E/K), aktif (0/1) gibi sütunlar için tek başına indeks genellikle full scan'den yavaş kalır. Optimizer, tablonun %50'sini dönüp dönmeyeceğini hesaplayıp indeksi atlayabilir. Bu sütunları composite indekste kullanmak daha verimlidir.
2. Çok küçük tablolar: 10.000 satırın altındaki tablolarda full scan çoğunlukla indeks lookup'tan hızlıdır — InnoDB buffer pool zaten tüm tabloyu RAM'de tutabilir.
3. Yazma yoğun tablolar: Her INSERT/UPDATE/DELETE ilgili tüm indeksleri günceller. Log tabloları, event stream gibi sürekli yazılan tablolarda fazla indeks yazma darboğazı yaratır.
-- Kullanılmayan indeksleri tespit et (MySQL 8.0 sys schema)
SELECT object_schema, object_name, index_name
FROM sys.schema_unused_indexes
WHERE object_schema NOT IN ('mysql', 'performance_schema', 'sys');
-- PostgreSQL'de kullanılmayan indeksler
SELECT schemaname, tablename, indexname,
pg_size_pretty(pg_relation_size(indexrelid)) AS boyut,
idx_scan AS kullanim_sayisi
FROM pg_stat_user_indexes
WHERE idx_scan = 0
ORDER BY pg_relation_size(indexrelid) DESC;
-- Kullanılmayan indeksi sil
DROP INDEX idx_eski ON siparisler;
İndeks Bakımı: ANALYZE, OPTIMIZE, pt-online-schema-change
İstatistikleri Güncelleme
Optimizer, indeks seçerken istatistikleri kullanır. Tablo çok değişmişse istatistikler eski kalır ve kötü plan seçilir.
-- MySQL / MariaDB
ANALYZE TABLE siparisler; -- istatistikleri güncelle (tablo kilitlenmez)
-- PostgreSQL
ANALYZE siparisler; -- istatistikleri güncelle
VACUUM ANALYZE siparisler; -- dead tuple temizle + istatistik güncelle
Parçalanmış İndeks Yeniden Oluşturma
-- MySQL / MariaDB: InnoDB defrag (online)
OPTIMIZE TABLE siparisler;
-- PostgreSQL: kilitsiz yeniden oluşturma (pg 12+)
REINDEX INDEX CONCURRENTLY idx_musteri_id;
REINDEX TABLE CONCURRENTLY siparisler;
Büyük Tablolarda Downtime'sız ALTER — pt-online-schema-change
Büyük tabloya indeks eklemek tablo kilidine neden olabilir. pt-online-schema-change arka planda shadow tablo oluşturarak sıfır kesintili ALTER sağlar:
# Yeni indeks ekle, tablo kilitlenmez
pt-online-schema-change --host=localhost --user=root --password=SIFRE --alter "ADD INDEX idx_yeni (musteri_id, durum)" D=veritabani,t=siparisler --execute
WordPress İçin İndeks Optimizasyonu
WordPress'in en sık yavaşlayan tabloları: wp_options (autoload), wp_postmeta, wp_posts.
-- wp_options autoload boyutu kontrol
SELECT ROUND(SUM(LENGTH(option_value)) / 1024 / 1024, 2) AS mb
FROM wp_options WHERE autoload = 'yes';
-- 1 MB üzeriyse indeks + autoload temizliği şart (ID 244 wp_options rehberi)
-- wp_options autoload için indeks
ALTER TABLE wp_options ADD INDEX idx_autoload (autoload);
-- wp_postmeta: meta_key araması için composite indeks
ALTER TABLE wp_postmeta ADD INDEX idx_meta_key_value (meta_key, meta_value(20));
-- wp_posts: post_type + post_status + post_date — WP en sık sorgular
ALTER TABLE wp_posts ADD INDEX idx_type_status_date (post_type, post_status, post_date);
-- Covering: sadece ID ve başlık listesi çeken sorgular için
ALTER TABLE wp_posts ADD INDEX idx_cover_list (post_type, post_status, ID, post_title);
Yavaş WordPress sorguları tespit için Query Monitor eklentisi kurun: her sayfa yüklemesinde çalışan sorguları, sürelerini ve EXPLAIN çıktısını gösterir.
WooCommerce İndeks İpuçları
WooCommerce 7+ ile wp_woocommerce_orders tablosu büyük sitelerde hızla şişer.
-- Sipariş durumuna göre filtreleme
ALTER TABLE wp_woocommerce_orders
ADD INDEX idx_status_date (status, date_created_gmt);
-- Müşteri siparişleri
ALTER TABLE wp_woocommerce_orders
ADD INDEX idx_customer_status (customer_id, status);
-- wp_postmeta'da WooCommerce sipariş meta aramaları
ALTER TABLE wp_postmeta ADD INDEX idx_wc_order_meta
(meta_key, meta_value(30));
WooCommerce özel raporlama sorguları yazarken daima EXPLAIN çalıştırın — type=ALL ve yüksek rows değeri görürseniz composite indeks ekleyin.
PostgreSQL'e Özgü Güçlü Özellikler
Partial Index — Sadece İlgili Satırlar
Tam tablo yerine bir WHERE koşulunu karşılayan satırları indeksler. Hem boyut küçük hem de sorgular daha hızlı.
-- Yalnızca aktif kullanıcıları indeksle
CREATE INDEX idx_aktif_kullanici ON kullanicilar(email)
WHERE aktif = true;
-- Tabloda 1M kullanıcı, 50K aktif → indeks sadece 50K satırı tutar
-- Silinmemiş siparişler için
CREATE INDEX idx_aktif_siparis ON siparisler(musteri_id, tarih)
WHERE silinmis = false;
Expression Index — Fonksiyon Sonucunu İndeksle
-- Büyük/küçük harf duyarsız e-posta araması
CREATE INDEX idx_lower_email ON kullanicilar(LOWER(email));
SELECT * FROM kullanicilar WHERE LOWER(email) = '[email protected]'; -- indeks kullanır
-- JSON alanından belirli key
CREATE INDEX idx_json_kategori ON urunler((meta->>'kategori'));
SELECT * FROM urunler WHERE meta->>'kategori' = 'elektronik';
GIN ile JSONB — PostgreSQL'in Üstünlüğü
MySQL'de JSON sütununda içerik araması için ayrı sütunlar ve indeksler gerekir. PostgreSQL'de tek GIN indeks tüm JSONB yapısını kapsar.
CREATE INDEX idx_gin_json ON urunler USING GIN(ozellikler);
SELECT * FROM urunler WHERE ozellikler @> '{"ram": "16GB", "ekran": "4K"}';
-- Tek indeks, her JSON kombinasyonu için çalışır
Foreign Key ve JOIN Performansı
InnoDB'de foreign key sütunları otomatik indekslenir. Ama referans eden tablo (child) tarafındaki FK sütunu için indeks eklemek zorundasınız — MySQL bunu otomatik yapmaz.
-- Parent: kullanicilar(id) PRIMARY KEY → zaten indekslendi
-- Child: siparisler(musteri_id) REFERENCES kullanicilar(id)
-- Bu indeks yoksa JOIN'de tam tablo taraması olur
CREATE INDEX idx_siparis_musteri ON siparisler(musteri_id);
-- Doğrulama
EXPLAIN SELECT u.ad, s.tutar
FROM kullanicilar u
JOIN siparisler s ON u.id = s.musteri_id
WHERE u.id = 1234;
-- type=eq_ref (kullanicilar) + type=ref (siparisler) → iyi ✓
JOIN'de her iki taraftaki birleştirme sütunu indekslenmiş olmalı; yoksa JOIN karmaşıklığı O(n²)'ye döner.
Buyukweb Hosting'de İndeks Yönetimi
cPanel + MariaDB 10.6 (Paylaşımlı Hosting):
- phpMyAdmin > Yapı (Structure) > İndeksler bölümünden indeks ekleyip silebilirsiniz
SHOW INDEX FROM tablokomutunu phpMyAdmin SQL sekmesinden çalıştırın- Slow query log açılması için destek talebi açın: 0850 302 60 70
EXPLAINveANALYZE TABLEtam yetkiyle çalışır
VDS (Bursa Tier 3 veri merkezi):
- Root yetkisi — MariaDB 10.11 veya MySQL 8.0 kurabilir,
my.cnfdüzenleyebilirsiniz slow_query_log,performance_schema, pt-query-digest tam kullanılabilir- Redis Object Cache entegrasyonu için ID 173 MySQL performans rehberine bakın
- Büyük tablolarda pt-online-schema-change ile sıfır kesintili ALTER
Buyukweb VDS'lerinde NVMe SSD ile indeks lookup I/O süresi minimize edilir — doğru indeks kurgusu ile çoğu sorgu tek haneli milisaniyeye iner.
Sıkça Sorulan Sorular
Hangi sütunlara indeks eklenmeli?
WHERE koşullarında sık kullanılan sütunlar, JOIN bağlantılarındaki foreign key sütunları, ORDER BY ve GROUP BY sütunları önceliklidir. Kardinalitesi yüksek (çok sayıda benzersiz değer: email, ID, timestamp) sütunlar tek başına indeks için en uygundur. Düşük kardinaliteli sütunlar (boolean, 3-4 değerli enum) composite indeks içinde daha işe yarar.
Composite indeks mi, ayrı ayrı indeks mi?
Sorgularınız genellikle aynı sütun kombinasyonunu birlikte kullandığında composite indeks daha verimlidir — tek indeks hem WHERE hem ORDER BY'ı karşılar, covering index olabilir. Sütunlar bağımsız sorgularda da kullanılıyorsa ayrı indeksler tercih edilebilir; ancak fazla indeks yazma maliyetini artırır.
EXPLAIN type=ALL görüyorum, nasıl düzelir?
İlgili WHERE sütununa indeks ekleyin. Birden fazla WHERE sütunu varsa composite indeks oluşturun (önce eşitlik koşullundaki yüksek kardinaliteli sütun). İndeks ekledikten sonra ANALYZE TABLE çalıştırın, ardından EXPLAIN tekrar kontrol edin — type değeri ref veya range'e dönmeli.
Çok fazla indeks performansı yavaşlatır mı?
Evet. Her indeks, INSERT/UPDATE/DELETE işlemlerinde otomatik güncellenir. Yazma yoğun tablolarda 10+ indeks ciddi yavaşlamaya neden olabilir. sys.schema_unused_indexes (MySQL) veya pg_stat_user_indexes (PostgreSQL) ile kullanılmayan indeksleri tespit edip silin.
GIN indeks nedir, B-Tree'den farkı ne?
GIN (Generalized Inverted Index), bir değerin içindeki elemanları indeksler: dizinin her öğesi, JSONB'nin her key-value, tam metin aramasının her kelimesi. B-Tree skaler değerlerin sıralı ağacını tutar. Dizi/JSONB/tsvector araması için GIN şarttır; basit eşitlik/aralık için B-Tree daha hafif ve hızlıdır.
WordPress'te hangi ek indeksler önerilir?
wp_options tablosunda autoload sütununa indeks, wp_postmeta tablosunda (meta_key, meta_value(20)) composite indeks, wp_posts tablosunda (post_type, post_status, post_date) composite indeks en kritik olanlardır. Query Monitor eklentisi ile yavaş sorguları bulun ve EXPLAIN ile doğrulayın.
cPanel'de slow query log kullanabilir miyim?
Paylaşımlı hosting'de SET GLOBAL yetkisi bulunmadığından doğrudan açamazsınız. phpMyAdmin > Status sekmesinden Slow_queries sayacını izleyebilirsiniz. Ayrıca WordPress Query Monitor veya uygulama tarafı loglama (Laravel Debugbar gibi) ile yavaş sorguları tespit edebilirsiniz. Slow query log açılması için destek hattımızı arayın: 0850 302 60 70.
İlgili Büyükweb Hizmetleri
Veritabanı odaklı uygulamalar için altyapı seçeneklerimiz:
- cPanel Web Hosting — MariaDB 10.6 LTS, phpMyAdmin dahil
- VDS Sunucu — root yetkili, MySQL 8.0 / MariaDB 10.11 serbestçe kurulabilir
- E5 v4 VDS — NVMe SSD, yüksek IOPS, veritabanı yoğun iş yükleri için
- WordPress Hosting — LiteSpeed + MariaDB optimize
Teknik destek için 0850 302 60 70 numaralı hattımızı arayın veya iletişim sayfamızı ziyaret edin.
Veritabanı Yönetimi İlgili Hizmetlerimiz
Bu yazıda anlatılan teknik konuyu profesyonel altyapıyla deneyimleyin
Etiketler:

