SQL index, veritabanının aranan kayıtları bulmak için tablonun tamamını okumak yerine kullanabileceği ek bir erişim yoludur. Bir sorgu çok sayıda satır arasından az sayıda kaydı seçmeye çalışıyorsa uygun bir index, arama maliyetini azaltabilir; ancak index eklemek sorguyu her durumda hızlandırmaz ve veritabanı yöneticisi her sorguda index kullanmayı tercih etmek zorunda değildir.
Index mantığını anlamanın en kolay yolu kitap sonundaki dizini düşünmektir. Belirli bir konuyu bulmak için kitabın her sayfasını tek tek okumak yerine dizindeki konu başlığını arar, ardından ilgili sayfaya geçersiniz. SQL tablosundaki tablo taraması buna karşılık kitabın tamamını okumaya; index üzerinden erişim ise önce düzenlenmiş arama yapıp gerekli satırlara gitmeye benzer.
SQL Index Nedir ve Sorguyu Neden Hızlandırabilir?
Bir SQL tablosu, uygulamanın verileri kalıcı olarak sakladığı ana yapıdır. Örneğin bir sipariş tablosunda sipariş numarası, müşteri numarası, sipariş durumu ve oluşturulma tarihi gibi sütunlar bulunabilir. Uygulama belirli bir müşterinin siparişlerini istediğinde veritabanı bu isteği karşılamak için farklı erişim yollarını değerlendirebilir.
Index yoksa veritabanı, aranan koşulu bulmak için tablonun satırlarını baştan sona kontrol etmek zorunda kalabilir. Bu işlem tablo taraması veya full scan olarak adlandırılır. Tablo küçük olduğunda bu yaklaşım pratik olabilir. Fakat satır sayısı arttıkça, yalnızca birkaç kaydı bulmak için çok sayıda satırın okunması gereksiz iş oluşturabilir.
Index, tablonun yerine geçen ikinci bir tablo değildir. Daha doğru ifadeyle, belirli sütunlardaki değerleri düzenleyen ve bu değerlerin ait olduğu satırlara ulaşmak için gerekli bilgiyi tutan yardımcı bir veri yapısıdır. Bu yapı sayesinde veritabanı, örneğin customer_id = 42 koşulunu ararken bütün kayıtları sırayla incelemek yerine index içinde ilgili değerin bulunduğu konuma yönelebilir.
Basitleştirilmiş bir index kaydı şu iki bilgiyi içeriyor gibi düşünülebilir:
- Arama yapılan sütunun değeri: örneğin
42 - Bu değere sahip asıl tablo satırına erişim bilgisi
Gerçek uygulamalarda index yapısının iç düzeni kullanılan veritabanı motoruna, index türüne ve sütunun veri tipine göre değişebilir. Sık karşılaşılan sıralı index yapıları eşitlik ve aralık aramalarında kullanılabilecek biçimde düzenlenir. Örneğin bir tarih sütununda belirli bir güne eşit kayıtları veya iki tarih arasındaki kayıtları aramak bu mantığa uygundur. Bununla birlikte index yapısının varlığı tek başına belirli bir sorgunun mutlaka hızlı çalışacağı anlamına gelmez.
Tablo taraması ile index üzerinden arama arasındaki fark
Bir kütüphanede milyonlarca kitabın raflara gelişigüzel yerleştirildiğini düşünün. “Yazılım mimarisi” konusunu bulmak için her kitabın kapağına bakmanız gerekir. Bu, tablo taramasına benzer. Eğer kitapların konularını gösteren düzenli bir katalog varsa önce katalogda arama yapar, ardından yalnızca ilgili raflara yönelirsiniz. Index de veritabanına benzer bir yön bulma bilgisi sağlar.
Ancak index araması genellikle iki aşamalıdır:
- Veritabanı index içinde koşula uyan değerleri bulur.
- Bulunan değerlerin işaret ettiği asıl tablo satırlarını okur.
Bu nedenle index, her durumda tabloyu tamamen ortadan kaldırmaz. Sorgu SELECT * ile çok sayıda sütun istiyorsa veya eşleşen satır sayısı yüksekse, indexte bulunan kayıtların ardından tablodan çok sayıda satır çekilmesi gerekir. Böyle bir durumda index üzerinden gidip tekrar tabloya dönmek, doğrudan tabloyu sıralı okumaktan daha avantajlı olmayabilir.
Veritabanı optimizer’ı bu seçimi tahmini maliyetlere göre yapar. Koşulun kaç satırla eşleşebileceği, verilerin nasıl dağıldığı, indexin düzeni, sorgunun istediği sütunlar ve fiziksel okuma maliyeti birlikte değerlendirilir. Resmî veritabanı dokümantasyonlarında da indexlerin performansı artırabildiği, ancak uygunsuz index kullanımının ek yük oluşturabileceği özellikle vurgulanır. ([postgresql.org](https://www.postgresql.org/docs/current/sql-createindex.html?utm_source=openai))
Index neden her zaman daha hızlı değildir?
Index en çok, büyük bir veri kümesinden görece az sayıda satır seçildiğinde anlamlıdır. Örneğin bir tabloda binlerce kayıt varken yalnızca tek bir müşterinin kayıtlarını aramak index için uygun bir senaryo olabilir. Buna karşılık sorgu tablonun büyük bölümünü döndürecekse veritabanı, indexten satır satır ilerlemek yerine tabloyu daha düzenli bir biçimde taramayı seçebilir.
Bu durum “index çalışmadı” şeklinde yorumlanmamalıdır. Optimizer, mevcut koşullar altında tablo taramasını daha düşük maliyetli görmüş olabilir. Örneğin aşağıdaki iki sorgunun erişim tercihi aynı olmak zorunda değildir:
WHERE customer_id = 42: Az sayıda müşteriye ait kayıt dönüyorsa index erişimi uygun olabilir.WHERE status = 'active': Eğer satırların büyük bölümü aynı duruma sahipse tablo taraması daha makul görülebilir.
Buradaki temel kavram seçiciliktir. Seçicilik, bir koşulun toplam kayıtlar içinden ne kadar küçük bir bölümü ayırabildiğini anlatır. Benzersiz bir sipariş numarası genellikle yüksek seçiciliğe sahiptir; birkaç farklı değerden oluşan bir durum sütunu ise daha düşük seçiciliğe sahip olabilir. Düşük seçicilik, indexin hiçbir zaman kullanılamayacağı anlamına gelmez. Yalnızca indexin sağlayacağı kazancın sorguya, veri dağılımına ve dönen satır sayısına bağlı olduğu anlamına gelir.
Python veya Java uygulaması indexi nasıl “görür”?
Python ya da Java ile yazılmış bir uygulama veritabanına SQL sorgusu gönderdiğinde index seçme kararını genellikle uygulama kodu vermez. Uygulama sorguyu, parametreleri ve bağlantı bilgilerini iletir; sorgunun hangi erişim planıyla çalıştırılacağını veritabanı motorunun optimizer’ı belirler.
Örneğin Python ile geliştirilen bir sipariş ekranı, kullanıcının seçtiği müşteri numarasına göre şu mantıktaki sorguyu gönderebilir:
CREATE TABLE orders (
id INTEGER,
customer_id INTEGER,
status VARCHAR(20)
);
CREATE INDEX idx_orders_customer_id
ON orders (customer_id);
SELECT id, status
FROM orders
WHERE customer_id = 42;
Bu örnekte index, customer_id değerine göre arama yapılabilmesi için oluşturulmuştur. Sorgunun gerçekten index kullanıp kullanmadığı ise yalnızca CREATE INDEX komutuna bakılarak anlaşılmaz. Bunun için ilgili veritabanı motorunun plan inceleme özelliği, çoğu sistemde EXPLAIN komutunun uygun biçimi, kullanılmalıdır.
Indexin tablo verilerinden ayrı tutulması ayrıca bir bakım maliyeti doğurur. Yeni bir satır eklendiğinde, indexlenen sütunlardan biri değiştirildiğinde veya satır silindiğinde index yapısının da güncellenmesi gerekir. Bu yüzden “daha fazla index her zaman daha iyi performans” yaklaşımı doğru değildir. Index, gerçek sorgu desenine göre seçilen bir erişim yatırımıdır; kullanılmayan veya gereksiz indexler yazma işlemlerini ağırlaştırabilir ve depolama tüketebilir.
WHERE, JOIN ve ORDER BY Index Kullanımını Nasıl Değiştirir?

Bir indexin faydasını değerlendirirken yalnızca “hangi sütunda index var?” sorusuna bakmak yeterli değildir. Sorgunun bu sütunu nasıl kullandığı da önemlidir. WHERE, JOIN ve ORDER BY ifadeleri indexten farklı şekillerde yararlanabilir. Optimizer; koşulun yapısını, veri dağılımını, seçiciliği ve sorgunun kaç satır döndüreceğini değerlendirerek index erişimi ile tablo taraması arasında seçim yapar.
WHERE koşulunda belirli kayıtları bulmak
WHERE koşulu, index kullanımının en kolay fark edildiği alandır. Eşitlik karşılaştırmaları, aralık koşulları ve bazı sıralanabilir veri tipleri üzerindeki karşılaştırmalar index aramasına uygun olabilir. Örneğin şu sorgu belirli bir tarih aralığındaki siparişleri bulmayı amaçlar:
SELECT id, customer_id, status
FROM orders
WHERE created_at >= '2026-01-01'
AND created_at < '2026-02-01';
Burada index kullanımı; ilgili sütunda uygun bir index bulunmasına, tarih değerlerinin dağılımına ve sorgunun kaç satır döndüreceğine bağlıdır. Sorgu sonuçların büyük bölümünü getiriyorsa optimizer index yerine tablo taramasını seçebilir.
Indexlenen sütuna bir fonksiyon uygulandığında, basit sütun araması ile aynı durum oluşmayabilir. Örneğin LOWER(email) = '...' veya bir tarih sütunundan yıl çıkarmaya dayalı bir koşul, doğrudan sütun değerini karşılaştırmaktan farklı değerlendirilir. Bazı veritabanı motorları bu tür ifadeler için expression veya function-based index desteği sunabilir; ancak bu özelliklerin sözdizimi ve kullanım şartları motora göre değişir. Resmî dokümantasyonlarda, ifadeye dayalı indexlerin arama hızına katkı sağlayabildiği fakat ekleme ve güncelleme sırasında bakım maliyeti oluşturduğu belirtilir. ([postgresql.org](https://www.postgresql.org/docs/current/indexes-expressional.html?utm_source=openai))
Metin aramalarında da sorgunun biçimi önemlidir. Baştan başlayan bir desen, örneğin name LIKE 'Ali%', bazı sıralı index yapılarıyla uyumlu olabilir. Buna karşılık name LIKE '%ali%' ifadesinde aranan karakter dizisi metnin herhangi bir yerinde bulunabileceği için indexin arama alanını daraltması zorlaşabilir. Bu davranış veri tabanı motoruna, collation ayarlarına ve index türüne göre değişebileceğinden, motor-bağımsız bir kural gibi ele alınmamalıdır. Örneğin resmî dokümantasyonlarda başında joker karakter olmayan LIKE desenleri için index aralığı oluşturulabileceği, başında joker karakter bulunan desenlerin ise farklı değerlendirildiği açıklanır. ([postgresql.org](https://www.postgresql.org/docs/current/indexes-types.html?utm_source=openai))
JOIN sırasında eşleşen anahtarları aramak
JOIN işlemlerinde veritabanı iki veya daha fazla tablodaki ilişkili kayıtları birleştirir. Örneğin orders.customer_id ile customers.id sütunları üzerinden müşterileri ve siparişleri eşleştiren bir sorgu düşünelim. Bu eşleştirme sırasında index, bir tablodan okunan anahtar değerine karşılık diğer tabloda ilgili satırların daha hızlı bulunmasına yardımcı olabilir.
Fakat burada da indexin varlığı tek başına yeterli değildir. Optimizer aşağıdaki noktaları birlikte değerlendirir:
- Hangi tablonun önce okunmasının daha az maliyetli olduğu
- JOIN koşulunun eşitlik veya aralık karşılaştırması içerip içermediği
- Bir anahtar değerinin ortalama kaç satırla eşleştiği
- Filtrelerin JOIN işleminden önce mi sonra mı uygulanabildiği
- Sorgunun toplamda kaç satır döndüreceği
Bir JOIN sütununda index bulunması, özellikle bir tablodan gelen her anahtar için diğer tabloda arama yapılacak planlarda yararlı olabilir. Buna karşılık iki tablonun büyük bölümü birbiriyle eşleşiyorsa, index üzerinden çok sayıda ayrı satır aramak yerine daha geniş bir tarama veya farklı bir JOIN stratejisi tercih edilebilir.
ORDER BY ile sıralama maliyetini azaltmak
ORDER BY kullanılan sorgularda index, yalnızca kayıt bulma amacıyla değil, sonuçları istenen sıraya daha yakın biçimde sunma amacıyla da değerlendirilebilir. Indexin sıralı yapısı sorgunun istediği sütun sırasıyla uyumluysa, veritabanı ayrıca büyük bir sonuç kümesini baştan sona sıralamak zorunda kalmayabilir.
Örneğin şu sorgu, son oluşturulan siparişleri sıralamak ister:
SELECT id, customer_id, created_at
FROM orders
WHERE customer_id = 42
ORDER BY created_at DESC;
Bu sorguda yalnızca customer_id üzerinde index bulunması, filtrelemeye yardımcı olabilir; fakat created_at sıralamasını ayrıca ele almak gerekebilir. Birden fazla sütunu içeren bileşik index tasarımı gündeme geldiğinde sütunların sırası önem kazanır. Ancak bileşik index kuralları ve optimizer davranışı veritabanı motorlarına göre farklılaşabildiği için tek bir ürünün kuralı bütün SQL sistemlerine genellenmemelidir.
Ayrıca index üzerinden sıralama yapmak her zaman doğrudan sıralama işleminden daha hızlı değildir. Sorgu tablonun büyük bölümünü okuyacaksa index sırasındaki satırlara tek tek ulaşmak, tabloyu toplu biçimde okuyup sonuçları sıralamaktan daha maliyetli olabilir. Bu nedenle index var mı? sorusundan önce bu sorgu kaç satır okuyacak ve kaç satır döndürecek? sorusunu sormak gerekir. Bazı resmî dokümantasyonlarda optimizer’ın index sırasını kullanma ile tabloyu okuyup ayrıca sıralama seçeneklerini maliyet bakımından karşılaştırdığı belirtilir. ([postgresql.org](https://www.postgresql.org/docs/current/indexes-ordering.html?utm_source=openai))
Özetle WHERE, JOIN ve ORDER BY ifadeleri indexten yararlanabilecek üç önemli kullanım alanıdır; ancak index kullanımı yalnızca sütun üzerinde bir yapı bulunmasına bağlı değildir. Koşulun yazılış biçimi, fonksiyon ve dönüşümler, metin deseninin başlangıcı, bileşik indexteki sütun sırası, veri dağılımı ve sonuç kümesinin büyüklüğü birlikte değerlendirilir. Bu yüzden performans sorunu yaşayan bir sorguda ilk adım rastgele index eklemek değil, sorgunun gerçek erişim planını incelemek olmalıdır.
EXPLAIN ile Sorgunun Tabloyu Nasıl Taramasını Okumak
EXPLAIN, veritabanı motorunun bir sorguyu çalıştırırken hangi erişim yolunu seçmeyi planladığını görmenizi sağlar. Planı incelerken yalnızca “index kullanılmış mı?” sorusuna bakmak yeterli değildir; tablonun ne kadarının tarandığı, koşulun nerede uygulandığı, tahmini kaç satırın incelendiği ve sıralama için ek bir işlem gerekip gerekmediği birlikte değerlendirilmelidir.
EXPLAIN çıktısında kullanılan komutun yazımı, plan düğümlerinin adları ve sütun isimleri veritabanı motoruna göre değişebilir. Örneğin bir sistemde sıralı tablo taraması Seq Scan, başka bir sistemde Full Table Scan veya benzer bir ifadeyle gösterilebilir. Aynı şekilde index erişimi Index Scan, Index Range Scan ya da motorun kendi terminolojisiyle görüntülenebilir. Bu nedenle aşağıdaki örnek, belirli bir ürüne ait birebir çıktı değil, EXPLAIN mantığını açıklayan temsili bir gösterimdir. Gerçek projede kullandığınız motorun dokümantasyonundaki sözdizimi ve plan alanları ayrıca kontrol edilmelidir. PostgreSQL EXPLAIN dokümantasyonu plan düğümleri, tahmini maliyet, tahmini satır sayısı ve filtreleme gibi kavramların nasıl raporlanabildiğini gösteren örneklerden biridir.
-- Sorgu
EXPLAIN
SELECT id, email
FROM users
WHERE email = '[email protected]';
-- Index yokken: temsili plan
FULL SCAN users
condition: email = '[email protected]'
estimated rows examined: many
filter applied: after table read
-- email sütununda uygun index varken: temsili plan
INDEX ACCESS users_email_idx
condition: email = '[email protected]'
estimated rows examined: few
filter applied: during index lookup
İlk planda veritabanı, users tablosundaki kayıtları geniş biçimde taramak zorunda kalabilir. Sorgunun WHERE email = ... koşulu bulunmasına rağmen bu koşulun yazılmış olması tek başına hızlı erişim anlamına gelmez. Eğer aranan sütunu kullanabileceği uygun bir index yoksa motor, satırları okuyup her satır için koşulu kontrol edebilir. Bu davranış, plan çıktısında full scan veya sequential scan benzeri bir ifadeyle görülebilir.
İkinci planda ise motor, email sütunundaki index üzerinden arama yapabilir. Böylece önce index yapısında aranan değerin konumunu bulur, ardından gerekli kayıtları tablodan veya index içindeki bilgilerden getirir. Buradaki önemli fikir, index’in tabloyu sihirli biçimde hızlandırması değil, aranan kayda ulaşmak için incelenmesi gereken veri miktarını azaltabilmesidir.
Planı okurken ilk olarak erişim yolunu bulun
EXPLAIN çıktısının en önemli bölümlerinden biri, tablonun nasıl okunduğunu gösteren plan düğümüdür. İlk incelemede şu soruyu sorun: “Motor bu tabloya doğrudan mı gidiyor, yoksa önce bir index üzerinden daraltma mı yapıyor?”
- Full scan veya sequential scan: Tablonun büyük bölümünün ya da tamamının okunması söz konusu olabilir.
- Index erişimi: Arama, sıralama veya join koşulunda kullanılabilecek bir index yolu seçilmiş olabilir.
- Bitmap benzeri erişim: Bazı motorlar birden fazla eşleşen kaydı toplu biçimde bulup daha sonra tablodan okuyabilir.
- Sort veya temporary benzeri adımlar: Sorgunun istediği sıralamayı oluşturmak için ayrıca veri düzenleme işlemi yapılabilir.
- Join planı: Birden fazla tablo varsa hangi tablonun önce okunduğu ve diğer tabloyla nasıl eşleştirildiği görülebilir.
Full scan ifadesini gördüğünüzde hemen “bu sorgu kesinlikle hatalıdır” sonucuna varmayın. Tablo küçükse veya sorgu satırların büyük bölümünü döndürüyorsa tabloyu baştan sona okumak, index üzerinden çok sayıda ayrı kayda gitmekten daha uygun olabilir. EXPLAIN’in amacı index kullanımını zorunlu kılmak değil, motorun neden belirli bir erişim yolunu seçtiğini anlamanıza yardımcı olmaktır.
“Estimated rows” değerini gerçek taranan satır sayısıyla karıştırmayın
Plan çıktılarında rows, estimated rows veya benzer adlarla görülen değer genellikle planlayıcının tahminidir. Bu değer her zaman fiziksel olarak kaç satırın okunduğunu anlatmaz. Bazı motorlarda çıktı satır sayısını, bazılarında incelenmesi beklenen satır sayısını veya her plan düğümünün tahmini sonucunu ifade edebilir.
Bu nedenle aşağıdaki ayrımı yapın:
- Sorgunun sonunda kullanıcıya kaç satır dönmesi bekleniyor?
- Tablo tarama düğümünün incelemesi beklenen satır sayısı nedir?
- Filtre uygulandıktan sonra kaç satır kalıyor?
- Alt plan düğümlerinin ürettiği satır sayısı üst düğümde nasıl değişiyor?
Örneğin bir sorgu yalnızca birkaç kayıt döndürecek gibi görünürken plan, tablonun büyük bölümünün taranacağını gösteriyorsa index ihtimali araştırılabilir. Ancak tahminler tablo istatistiklerine ve verinin dağılımına dayanır. Sütundaki değerlerin dağılımı değişmiş, istatistikler güncellenmemiş veya sorgudaki koşul gerçekte tahmin edilenden daha fazla kayıt döndürüyor olabilir. Bu yüzden tahmini satır sayısını kesin ölçüm olarak değil, planlayıcının karar verirken kullandığı bir işaret olarak yorumlayın.
Koşul nerede uygulanıyor?
Bir EXPLAIN planında WHERE koşulunu görmek tek başına yeterli değildir. Koşulun index erişim koşulu olarak mı, yoksa tablo satırları okunduktan sonra uygulanan bir filtre olarak mı kullanıldığına bakın.
Aranan koşul index erişiminin parçasıysa motor, kayıtları daha erken daraltabilir. Buna karşılık koşul yalnızca filtre olarak görünüyorsa motor önce daha geniş bir veri kümesini okuyup ardından satırları elemek zorunda kalabilir. İki durumda da sorgu aynı sonucu üretebilir; fark, gereksiz satırların ne kadar erken elendiğidir.
Bu ayrım özellikle birden fazla koşul içeren sorgularda önemlidir. Örneğin şu sorguyu ele alalım:
SELECT id, name
FROM users
WHERE status = 'active'
AND city = 'Izmir';
Plan, status koşulunu erişim sırasında kullanırken city koşulunu daha sonra filtreliyor olabilir. Bu durum mutlaka yanlış değildir. Hangi koşulun daha fazla satırı eleyeceği, sütunların veri dağılımı ve mevcut index yapısıyla birlikte değerlendirilir. Bu nedenle yalnızca sorgudaki koşulların sırasına bakarak planın aynı sırayla çalışacağını varsaymayın.
“Filter” ve “Index Condition” gibi ifadeleri nasıl yorumlamalı?
Motorlar farklı terimler kullansa da temel ayrım genellikle aynıdır:
- Index condition: Index, aranan kayıtları bulmak için doğrudan kullanılıyor olabilir.
- Filter: Okunan satırlar üzerinde ek koşul kontrolü yapılıyor olabilir.
- Join condition: İki tablodan gelen satırların hangi alanlar üzerinden eşleştirildiğini gösterir.
- Sort key: Sonucun hangi sütunlara göre sıralanacağını belirtir.
- Rows removed veya filtered: Okunan satırların bir bölümünün sonraki aşamada elendiğini gösterebilir.
Bir sorguda hem index erişimi hem de filtre bulunabilir. Bu, index’in işe yaramadığı anlamına gelmez. Index bir koşulla aday kayıt kümesini daraltmış, başka bir koşul ise kalan kayıtlar üzerinde uygulanmış olabilir. Burada sorulması gereken soru şudur: “Index, toplam okuma işini anlamlı biçimde azaltmış mı ve pahalı filtreleme işlemi mümkün olduğunca erken yapılmış mı?”
Sıralama için ek işlem gerekiyor mu?
EXPLAIN okurken yalnızca tablo tarama düğümüne odaklanmayın. ORDER BY içeren sorgularda planın ayrıca bir sıralama adımı oluşturup oluşturmadığını da kontrol edin.
Örneğin aşağıdaki sorgu, önce uygun kayıtları bulup sonra bunları sıralayabilir:
SELECT id, created_at, total
FROM orders
WHERE customer_id = 42
ORDER BY created_at DESC;
Plan içinde Sort, Filesort, Temporary veya benzer bir adım görülmesi, motorun sonuçları istenen sıraya getirmek için ek çalışma yaptığını gösterebilir. Bu ifade tek başına sorunun kesin olarak index eksikliği olduğunu kanıtlamaz. Sorgunun kaç satır döndürdüğü, sıralamanın hangi aşamada yapıldığı ve mevcut index’in filtre ile sıralamayı birlikte destekleyip desteklemediği incelenmelidir.
Özellikle sonuç kümesi genişse, filtreleme sonrasında hâlâ çok sayıda kayıt kalıyorsa sıralama maliyeti önem kazanabilir. Buna karşılık sorgu çok az kayıt döndürüyor veya bir limit ile erken duruyorsa ek sıralama adımının etkisi farklı olabilir. Bu nedenle planı tek bir kelimeye göre değil, bütün düğümlerin oluşturduğu akışa göre değerlendirin.
EXPLAIN inceleme kontrol listesi
Bir sorguyu analiz ederken aşağıdaki sırayı izlemek, yeni başlayanlar için daha sağlıklı bir yaklaşım sunar:
- Tablo erişimini bulun: Full scan, sequential scan veya index erişimi benzeri plan düğümlerini belirleyin.
- Koşulun kullanımını inceleyin:
WHEREkoşulu erişim sırasında mı, yoksa satırlar okunduktan sonra mı uygulanıyor? - Tahmini satır miktarını kontrol edin: Motor kaç satırın inceleneceğini ve kaç satırın sonuç olarak üretileceğini tahmin ediyor?
- Filtrelemenin erken olup olmadığını sorun: Gereksiz kayıtlar mümkün olduğunca alt plan düğümlerinde eleniyor mu?
- Sıralama ve geçici işlemleri arayın:
ORDER BY, gruplama veya join sonrasında ek bir sort/temporary adımı oluşuyor mu? - Join sırasını değerlendirin: Birden fazla tablo varsa hangi tablo önce okunuyor ve eşleşme hangi koşulla yapılıyor?
- Planı gerçek sorgu davranışıyla karşılaştırın: Tahminlerin uygulamadaki gözlemlerle uyuşup uyuşmadığını test ortamında kontrol edin.
Python veya Java uygulamasından gönderilen SQL sorgularında bu inceleme özellikle değerlidir. Uygulama kodu yalnızca sorguyu çalıştırır; sorgunun tabloya hangi yoldan erişeceğini çoğunlukla veritabanı planlayıcısı belirler. Bu nedenle uygulama tarafında sorgu süresini fark ettiğinizde yalnızca Python ya da Java kodunu değil, veritabanının erişim planını da incelemelisiniz.
İyi bir EXPLAIN okumasının sonucu “index var” veya “index yok” demekten daha kapsamlıdır. Asıl hedef, sorgunun hangi veri miktarını işlediğini, filtreyi ne zaman uyguladığını ve gereksiz okuma ya da sıralama adımlarının nerede oluştuğunu anlayabilmektir.
Index Eklemek Hangi Maliyetleri Beraberinde Getirir?

Index eklemek, okuma sorgularını hızlandırma ihtimali sunar; ancak bunun karşılığında veritabanı her değişiklik işleminde daha fazla yapı güncellemek zorunda kalabilir. Yeni kayıt ekleme, mevcut kaydı güncelleme veya kayıt silme sırasında yalnızca ana tablo değil, ilgili index yapıları da tutarlı hâle getirilmelidir.
Bu nedenle index kararını “sorgu yavaşsa index ekle” düzeyinde bırakmak doğru değildir. Bir index’in faydasını değerlendirirken okuma sıklığıyla birlikte yazma trafiğini, disk kullanımını, bakım ihtiyacını ve diğer index’lerle olan örtüşmesini de hesaba katmak gerekir.
INSERT işlemlerinde ek çalışma oluşur
Yeni bir kayıt eklendiğinde veritabanı, ana tabloya kaydı yazmanın yanında bu kaydın uygun index yapılarındaki yerini de oluşturmalıdır. Index’lenen sütunlardan biri yeni kayıtta bulunuyorsa, index ağacına veya ilgili erişim yapısına yeni bir giriş eklenir.
Bir tabloda çok sayıda index varsa tek bir INSERT işlemi birden fazla yapıyı etkileyebilir. Bu, index’lerin gereksiz olduğu anlamına gelmez; fakat yoğun kayıt eklenen tablolarda her index’in yazma maliyetiyle birlikte değerlendirilmesi gerektiğini gösterir.
Örneğin olay kayıtları, işlem geçmişi veya sensör verileri gibi sürekli yeni satır alan bir tabloda yalnızca ara sıra çalışan rapor sorguları için çok sayıda index oluşturmak dengeli olmayabilir. Okuma sorgusu kazanırken kayıt ekleme sürecinde sürekli bir bakım işi yaratabilirsiniz.
UPDATE işlemleri index’i de değiştirebilir
Güncellenen sütun index içinde yer alıyorsa, veritabanının eski index bilgisini değiştirmesi veya yeni değere göre yeniden konumlandırması gerekebilir. Bu durum özellikle sık değişen alanlarda önemlidir.
Örneğin bir kullanıcının last_login, status veya geçici işlem durumu gibi alanları sık güncelleniyorsa bu sütunlara eklenen index’ler, her güncellemede ek iş doğurabilir. Sütunun sorgularda gerçekten önemli olup olmadığı ile güncelleme sıklığı birlikte değerlendirilmelidir.
Bir güncelleme sorgusu index’lenen sütunu değiştirmese bile, güncellenen diğer alanlar nedeniyle tablo satırının fiziksel yerleşimi veya index erişim biçimi motorun iç çalışma modeline bağlı olarak etkilenebilir. Bu ayrıntılar veritabanı ürününe göre değişebileceği için belirli bir motor davranışını genellemek yerine, kullanılan sistemin plan ve bakım araçlarıyla doğrulama yapmak daha güvenlidir.
DELETE işlemlerinde index kayıtları temizlenir
Bir kayıt silindiğinde, ana tablodaki satırın kaldırılması yeterli değildir. Bu satıra karşılık gelen index girişlerinin de temizlenmesi gerekir. Dolayısıyla silme işlemleri de index sayısından ve index’lerin yapısından etkilenebilir.
Arşivleme veya toplu silme işlemleri yapan uygulamalarda bu maliyet daha görünür hâle gelebilir. Büyük miktarda kayıt üzerinde değişiklik yapmadan önce sorgu planının, işlem süresinin ve bakım etkisinin kontrollü bir ortamda incelenmesi gerekir.
Index’ler disk alanı ve bakım yükü oluşturur
Index, tablonun kendisinden bağımsız bir veri yapısı olarak ek depolama alanı kullanır. Index’in kapsadığı sütunların sayısı, veri tipleri, değerlerin uzunluğu ve index yapısının çalışma biçimi kullanılan alanı etkileyebilir.
Disk kullanımı tek başına bir problem değildir; ancak bir tabloda hangi index’lerin gerçekten kullanıldığı izlenmiyorsa zaman içinde gereksiz yapılar birikebilir. Kullanılmayan veya büyük ölçüde aynı sorguları destekleyen index’ler:
- Şema tasarımını daha zor anlaşılır hâle getirebilir.
- Yeni geliştiricilerin hangi index’in neden oluşturulduğunu anlamasını güçleştirebilir.
- Yazma işlemlerinde birden fazla yapının güncellenmesine yol açabilir.
- Bakım, yedekleme ve taşıma süreçlerinde ek veri yükü oluşturabilir.
- Sorgu planlayıcısının değerlendireceği seçeneklerin sayısını artırabilir.
Bu nedenle index oluştururken yalnızca “bu sütun WHERE içinde kullanılıyor” demek yeterli değildir. Sorgunun ne kadar sık çalıştığı, ne kadar veri döndürdüğü, tablonun ne sıklıkla değiştiği ve mevcut index’lerle ne kadar örtüştüğü de incelenmelidir.
Çok sayıda index her sorguyu hızlandırmaz
Bir tabloya her sık kullanılan sütun için ayrı ayrı index eklemek ilk bakışta güvenli görünebilir. Fakat veritabanı her sorguda bütün index’leri kullanmaz. Sorgunun döndürdüğü kayıt sayısı yüksekse, index üzerinden tek tek kayıtlara gitmek yerine tabloyu daha geniş biçimde okumayı tercih edebilir.
Ayrıca iki ayrı index’in sağladığı yollar büyük ölçüde aynı sorguları karşılıyorsa bu yapılar arasında gereksiz tekrar oluşabilir. Örneğin aynı sütunları benzer sırada içeren iki index, biri diğerinin kullanım alanını neredeyse tamamen kapsıyorsa birlikte tutulmaları yeniden sorgulanmalıdır.
Buradaki amaç mümkün olan en fazla index’i oluşturmak değil, uygulamanın gerçekten ihtiyaç duyduğu erişim yollarını seçmektir. Index’ler sorgu performansının tek çözümü değildir; sorgunun gereksiz sütunları seçmesi, fazla kayıt döndürmesi, uygun olmayan join koşulları kullanması veya veritabanı istatistiklerinin güncel olmaması da planı etkileyebilir.
Index envanterini düzenli olarak gözden geçirin
Bir index oluşturulduktan sonra karar süreci bitmiş sayılmaz. Uygulamanın sorguları zaman içinde değişebilir; bazı ekranlar kaldırılabilir, yeni raporlar eklenebilir veya tablonun veri dağılımı farklılaşabilir. Bu nedenle index’lerin kullanım amacını belgelemek ve periyodik olarak gözden geçirmek yararlıdır.
- Index hangi sorgu veya sorgu grubu için oluşturuldu?
- Bu sorgu uygulamada hâlâ çalışıyor mu?
- Index erişim planlarında gerçekten değerlendiriliyor mu?
- Başka bir index aynı ihtiyacı karşılıyor mu?
- Yazma trafiği arttığında oluşturduğu bakım maliyeti kabul edilebilir mi?
- Index’in kapsadığı sütunlar ve sıraları mevcut sorgularla hâlâ uyumlu mu?
Sonuç olarak index, yalnızca okuma hızını artıran pasif bir yardımcı yapı değildir. Her index; depolama alanı, yazma işlemleri ve bakım süreçleriyle birlikte değerlendirilmesi gereken bir şema kararıdır. En sağlıklı yaklaşım, önce yavaş sorguyu EXPLAIN ile incelemek, sonra ölçülebilir bir erişim problemi varsa uygun index’i denemek ve planın gerçekten iyileşip iyileşmediğini yeniden kontrol etmektir.
Index Hangi Durumlarda Faydasız veya Zararlı Olabilir?
Bir sütuna index eklemek, o sütunla yapılan her sorguyu otomatik olarak hızlandırmaz. Index’in faydası; tablonun boyutuna, sütundaki farklı değerlerin dağılımına, sorgunun kaç satır döndürdüğüne ve tablonun ne sıklıkla güncellendiğine bağlıdır. Bazı durumlarda veritabanı, index üzerinden arama yapmak yerine tabloyu baştan sona okumayı daha uygun görebilir.
Küçük tablolarda tablo taraması daha mantıklı olabilir
Tablo küçükse tüm satırları okumak zaten düşük maliyetli olabilir. Böyle bir tabloda index ağacında arama yapmak, bulunan kayıtların asıl tablo satırlarına erişmek ve ardından koşulu uygulamak; doğrudan tabloyu okumaktan daha avantajlı olmayabilir.
Örneğin birkaç yüz satırlık bir ayarlar tablosunda, tek bir sütuna index eklemek sorguyu gözle görülür biçimde iyileştirmeyebilir. Üstelik bu tabloya yeni satır ekleniyor veya mevcut satırlar güncelleniyorsa index’in de güncel tutulması gerekir. Bu nedenle küçük tablo gördüğünüz her yerde index oluşturmak yerine, önce sorgunun gerçek çalışma planını incelemek daha doğru yaklaşımdır.
Düşük seçicilikli sütunlarda index geniş sonuç kümeleri döndürebilir
Seçicilik, bir sütunun sorgu sonucunu ne kadar daraltabildiğini anlatır. Bir sütunda çok sayıda farklı değer bulunuyor ve aranan değer az sayıda satırda görülüyorsa seçicilik genellikle yüksektir. Buna karşılık sütun yalnızca birkaç farklı değer alıyorsa seçicilik düşüktür.
Örneğin durum sütununda yalnızca aktif ve pasif değerleri olduğunu düşünelim. Tablonun büyük bölümü aktif durumundaysa, WHERE durum = 'aktif' koşulu çok geniş bir satır kümesi döndürebilir. Index bu değeri bulabilir; ancak bulunan satırların büyük bölümüne erişmek gerektiğinde index üzerinden ilerlemenin maliyeti beklenen kazancı azaltabilir.
Bu noktada kesin bir kural koymak doğru değildir. Optimizer’ın düşük seçicilikli bir index’i tercih edip etmeyeceği; tablo boyutu, değer dağılımı, güncel istatistikler, sorgunun seçtiği sütunlar ve kullanılan veritabanı motorunun maliyet modeline göre değişebilir. Resmî dokümantasyonlarda da sorgu planlayıcının koşulların seçiciliğini ve tabloyla index’in tahmini maliyetlerini değerlendirdiği açıklanır; örneğin PostgreSQL Planner Statistics bu tahminlerin veri dağılımı ve tablo istatistikleriyle ilişkisini açıklar.
Sık güncellenen sütunlarda yazma maliyeti oluşur
Index yalnızca okuma sırasında kullanılan pasif bir yapı değildir. Index verilen sütunun değeri değiştiğinde, veritabanının ilgili index kaydını da güncellemesi gerekir. Bu işlem; INSERT, UPDATE ve DELETE operasyonlarına ek iş yükü getirebilir.
Özellikle sürekli değişen bir sütun için oluşturulan index şu soruyla değerlendirilmelidir: Bu index’in okuma sorgularında sağladığı kazanç, her yazma işlemindeki bakım maliyetini karşılıyor mu?
Örneğin bir kayıt tablosundaki son_gorulme veya durum alanı çok sık güncelleniyorsa, bu sütunlara eklenen index her güncellemede yeniden düzenlenebilir. Söz konusu sütunla yapılan kritik ve sık okuma sorguları yoksa index, toplam sistem performansını iyileştirmek yerine yazma işlemlerini ağırlaştırabilir.
Gereksiz çoklu index bakım ve disk maliyetini artırır
Aynı tabloya çok sayıda index eklemek ilk bakışta sorgu seçeneklerini artırıyor gibi görünür. Ancak her index diskte yer kaplar, yazma işlemlerinde güncellenir ve zaman içinde takip edilmesi gereken ek bir yapı oluşturur.
Benzer amaçlara hizmet eden index’ler de gereksiz tekrar yaratabilir. Örneğin ayrı ayrı oluşturulan iki index, sorguların gerçek filtreleme biçimine göre tek bir bileşik index kadar yararlı olmayabilir. Bunun tersi de mümkündür: Her sorguyu kapsayacak şekilde çok sayıda bileşik index üretmek, index sayısını hızla artırabilir.
Bu nedenle index tasarımında hedef, “mümkün olduğunca fazla index” değil, en sık ve en maliyetli sorguları destekleyen dengeli bir yapı kurmaktır.
| Durum | Neden index faydası sınırlı olabilir | Ne yapılmalı? |
|---|---|---|
| Küçük tablo | Tablonun tamamını okumak zaten düşük maliyetli olabilir. | Index eklemeden önce gerçek sorgu planını ve çalışma süresini karşılaştır. |
| Düşük seçicilikli sütun | Sorgu çok fazla satır döndürebilir; index araması sonrasında geniş bir kayıt kümesine erişmek gerekebilir. | Değer dağılımını, dönen satır sayısını ve planlayıcının tercihini birlikte değerlendir. |
| Sık güncellenen sütun | Her yazma işleminde index’in de güncellenmesi ek maliyet oluşturur. | Okuma kazancının yazma maliyetini karşılayıp karşılamadığını ölç. |
| Çok sayıda benzer index | Disk kullanımı ve bakım yükü artar; bazı index’ler hiç kullanılmayabilir. | Sorgu kayıtlarını incele, tekrar eden index’leri belirle ve yalnızca gerekli yapıları koru. |
Pratik sonuç şudur: Index kararında yalnızca sütunun adını veya sorguda kaç kez geçtiğini dikkate almayın. Değer dağılımı ve gerçek sorgu planı birlikte incelenmelidir. Bir index’in faydasını anlamanın en güvenilir yolu, aynı sorguyu index öncesi ve sonrası planla ve mümkünse gerçekçi veri hacmiyle karşılaştırmaktır.
Hangi Sütunlara Index Eklemeye Karar Vermeli?
Index ekleme kararı, “Bu sütun sorguda kullanılıyor, o hâlde index gerekir.” biçiminde verilmemelidir. Daha sağlıklı yaklaşım; gerçek sorguları toplamak, tekrar eden erişim desenlerini belirlemek, aday sütunları maliyetleriyle birlikte değerlendirmek ve sonucu EXPLAIN ile doğrulamaktır.
Python uygulamasında yazılan SQL sorgularını incelerken de aynı yöntem kullanılabilir. Uygulama katmanında sorgunun hangi parametrelerle, hangi sıklıkta ve kaç satır döndürecek şekilde çalıştığını anlamak için geliştirici önce sorgu mantığını netleştirmelidir. Python temellerinizi ölçmek isterseniz Python bilgi testi bu uygulama bağlamını değerlendirmek için yardımcı olabilir.
Index kararı için beş adımlı çerçeve
- Gerçek ve tekrarlanan sorguları toplayın.
Önce uygulamanın gerçekten çalıştırdığı sorgulara bakın. Sadece örnek sorgulara veya geliştiricinin tahminlerine dayanmayın. Listeleme ekranları, kullanıcı profil sorguları, raporlar, API istekleri ve arka planda çalışan görevler farklı erişim desenlerine sahip olabilir.
- WHERE, JOIN ve ORDER BY adaylarını belirleyin.
Filtrelemede kullanılan sütunlar, tabloları birbirine bağlayan anahtarlar ve sıralama yapılan alanlar ilk adaylardır. Ancak aday olmak, otomatik olarak index oluşturulacağı anlamına gelmez. Sütunun sorguda nasıl kullanıldığı ve koşulun kaç satır döndürdüğü ayrıca incelenmelidir.
- Seçiciliği ve tablo boyutunu değerlendirin.
Bir kullanıcı kimliği, sipariş numarası veya benzersiz kayıt anahtarı genellikle az sayıda satıra ulaşmayı sağlar. Buna karşılık birkaç farklı değer alan bir durum sütunu, sorguyu yeterince daraltmayabilir. Aynı sütun küçük bir tabloda gereksizken büyük bir tabloda anlamlı olabilir.
- Okuma-yazma dengesini kontrol edin.
Bir tablo yoğun biçimde okunuyor ama nadiren güncelleniyorsa index’in bakım maliyeti daha kabul edilebilir olabilir. Tersine, sürekli veri alan veya güncellenen bir tabloda her yeni index yazma maliyetini artırabilir. Karar, yalnızca tek bir sorgunun hızına göre değil, tablonun genel kullanım biçimine göre verilmelidir.
- EXPLAIN ile index öncesi ve sonrası planı karşılaştırın.
Index oluşturduktan sonra sorgunun gerçekten daha uygun bir erişim yöntemi kullanıp kullanmadığını kontrol edin. Sorgu planındaki tahmini satır sayısı, kullanılan erişim türü, filtreleme adımı ve toplam maliyet gibi bilgileri karşılaştırın. EXPLAIN sözdizimi ve çıktı alanları veritabanı motoruna göre değişebileceği için, kullanılan motorun kendi dokümantasyonuna göre yorum yapılmalıdır.
Sütun index’e uygun mu? Kontrol listesi
- Sütun, uygulamada gerçekten tekrarlanan bir sorgunun
WHERE,JOINveyaORDER BYbölümünde kullanılıyor mu? - Sorgu, tablonun küçük bir bölümünü mü döndürüyor, yoksa satırların büyük kısmına mı ulaşıyor?
- Sütunda kaç farklı değer var ve bu değerler satırlara dengeli mi dağılıyor?
- Tablo küçük olduğu için tam tablo taraması zaten yeterince hızlı olabilir mi?
- Sütun sık güncelleniyor mu?
- Bu index’in eklenmesi mevcut index’lerle gereksiz bir tekrar oluşturuyor mu?
- Index’in disk ve bakım maliyeti, destekleyeceği sorguların önemini haklı çıkarıyor mu?
- EXPLAIN planı, index eklenmeden önce gerçekten maliyetli bir erişim adımı gösteriyor mu?
- Index eklendikten sonra sorgunun planında ölçülebilir bir iyileşme görülüyor mu?
Karar çerçevesini iki farklı sütun üzerinden uygulamak
İki örnek, index kararının neden yalnızca “sorguda geçiyor mu?” sorusuyla verilemeyeceğini gösterir:
| Örnek sütun | Sorgu davranışı | İlk değerlendirme |
|---|---|---|
kullanici_id |
Kullanıcıya ait kayıtlar sık sık aranıyor ve her sorgu az sayıda satır döndürüyor. | Yüksek seçicilik ve tekrarlanan okuma ihtiyacı nedeniyle index adayı güçlüdür. |
durum |
Sütun az sayıda değer alıyor ve kayıtlar sürekli güncelleniyor. | Düşük seçicilik ve yüksek yazma maliyeti nedeniyle index kararı EXPLAIN ve gerçek kullanım ölçümüyle verilmelidir. |
İlk örnekte kullanıcı kimliğiyle yapılan sorguların hedeflediği kayıt kümesi dar olabilir. Bu durumda index, tabloyu baştan sona okumak yerine belirli kayıtlara ulaşmaya yardımcı olabilir. İkinci örnekte ise durum alanı sorguda sık geçse bile, değerlerin az olması ve sürekli değişmesi index’in beklenen faydayı sağlamamasına yol açabilir.
Bu karşılaştırma, index kararının sütun adından çok erişim deseni ile ilgili olduğunu gösterir. Aynı sütun bir sistemde yararlı, başka bir sistemde gereksiz olabilir; çünkü tablo boyutu, veri dağılımı, sorgu sıklığı ve yazma yoğunluğu değişir.
Basit karar ağacı
Aşağıdaki sorular, aday bir sütun için hızlı bir ön değerlendirme yapmanızı sağlar:
- Sütun hiçbir önemli ve tekrarlanan sorguda kullanılmıyorsa index eklemeyin.
- Sütun kullanılıyor ancak sorgu tablonun büyük bölümünü döndürüyorsa, index’in faydasını EXPLAIN ile doğrulayın.
- Sütun yüksek seçiciliğe sahip ve sorgu az sayıda satır döndürüyorsa index güçlü bir adaydır.
- Sütun düşük seçicilikliyse tablo boyutunu, değer dağılımını ve planlayıcının tahminlerini birlikte inceleyin.
- Sütun çok sık güncelleniyorsa okuma kazancını yazma maliyetiyle karşılaştırın.
- Benzer işlevde index’ler zaten varsa yeni bir index oluşturmadan önce mevcut yapıları değerlendirin.
Son karar şu ilkeye dayanmalıdır: Index’i yalnızca adı sık geçtiği için değil, ölçülebilir bir sorgu ihtiyacını karşıladığı ve bakım maliyetini haklı çıkardığı zaman ekleyin. Index oluşturmak bir tahmin değil, sorgu planı ve kullanım verileriyle doğrulanması gereken bir performans kararıdır.
Sık Sorulan Sorular
Her WHERE koşulunda kullanılan sütuna index eklemek gerekir mi?
Hayır. Bir sütunun WHERE koşulunda kullanılması yalnızca onu index adayı yapar. Tablonun boyutu, sütunun seçiciliği, sorgunun döndürdüğü satır sayısı, yazma sıklığı ve mevcut sorgu planı birlikte değerlendirilmelidir. Küçük tablolarda veya çok geniş sonuç döndüren koşullarda tablo taraması daha uygun olabilir.
Index ekledikten sonra sorgu neden hâlâ tablo taraması yapabilir?
Optimizer, index üzerinden aramanın ve ardından satırlara erişmenin toplam maliyetini tabloyu okumakla karşılaştırır. Index koşulu çok fazla satır döndürüyor, tablo küçük kalıyor, istatistikler güncel değil veya sorgunun yapısı index’ten yararlanmaya uygun değilse tam tablo taraması seçilebilir. Bu nedenle index’in varlığı kadar EXPLAIN çıktısındaki gerçek plan da önemlidir.
Bir sütunun düşük seçicilikli olduğunu nasıl anlayabilirim?
Sütunda az sayıda farklı değer bulunması ve bu değerlerin çok sayıda satırda tekrarlanması düşük seçiciliğe işaret eder. Örneğin yalnızca birkaç durum değeri içeren bir sütun buna adaydır. Ancak yalnızca farklı değer sayısına bakmak yeterli değildir; değerlerin dağılımı ve belirli bir sorgunun kaç satır döndürdüğü de incelenmelidir.
Çok fazla index yazma işlemlerini nasıl etkiler?
Yeni bir satır eklendiğinde veya index’li bir sütun güncellendiğinde ilgili index yapılarının da güncellenmesi gerekir. Index sayısı arttıkça bu bakım işlemleri için daha fazla kaynak kullanılabilir. Bu nedenle fazla index, okuma sorgularına yardımcı olsa bile ekleme, güncelleme ve silme işlemlerini ağırlaştırabilir.
Index performansını EXPLAIN ile değerlendirirken nelere bakmalıyım?
Öncelikle sorgunun hangi erişim yöntemini kullandığına, tahmini olarak kaç satır okuduğuna ve filtreleme işleminin hangi aşamada yapıldığına bakın. Index öncesi ve sonrası planları aynı veri koşullarında karşılaştırın. EXPLAIN çıktısındaki alanların anlamı veritabanı motoruna göre değişebileceğinden, değerleri kullanılan motorun resmî açıklamalarıyla birlikte yorumlayın.
Sağlıklı bir index kararı, varsayımdan çok gerçek sorgu davranışına, veri dağılımına ve bakım maliyetine dayanır.