Bir SQLite sorgusunun indeks kullanıp kullanmadığını görmek için sorgunun başına EXPLAIN QUERY PLAN yazmanız yeterlidir: sorgu çalıştırılmaz, bunun yerine SQLite'ın hangi tabloyu hangi sırayla okuyacağını, hangi indeksi seçtiğini ve sıralama için geçici bir yapıya ihtiyaç duyup duymadığını anlatan kısa bir ağaç döner. Çıktıda SCAN tablonun baştan sona okunacağını, SEARCH ise yalnızca bir bölümünün ziyaret edileceğini söyler; yavaş sorgu teşhisinin ilk adımı bu iki kelimeyi ayırt etmektir.
Bu yazıda plan ağacının her satırını örneklerle okuyacağız: tablo ve indeks taramaları, kapsayan (covering) indeksler, birleştirmelerde döngü sırası, USE TEMP B-TREE satırları, OR koşulları, alt sorgular ve indeksi devre dışı bırakan ifadeler. Ardından komut satırının .eqp ve deneysel .expert komutlarına bakacak, son olarak gerçekçi bir sorguyu adım adım hızlandıracağız. Planın neden böyle seçildiğini ve istatistiklerin rolünü ise ANALYZE ve sorgu planlayıcı yazısında ayrıca ele alıyoruz.
EXPLAIN ile EXPLAIN QUERY PLAN arasındaki fark

SQLite'ta bir ifadenin önüne iki farklı önek konabilir. Tek başına EXPLAIN, ifadenin derlendiği sanal makine (bytecode) programını satır satır listeler. Bu liste SQLite'ın iç işleyişini incelemek için değerlidir ama günlük performans çalışmasında okunması zordur ve belgelere göre biçimi yalnızca kısmen belgelenmiştir. EXPLAIN QUERY PLAN ise aynı bilgiyi üst düzeyde özetler: hangi tablo, hangi indeks, hangi WHERE terimleri. Gündelik kullanımda neredeyse her zaman ikincisine ihtiyacınız olur.
EXPLAIN SELECT id FROM siparis WHERE id = 3;
-- çıktı (ilk satırlar):
-- addr opcode p1 p2 p3 p4 p5 comment
-- ---- ------------- ---- ---- ---- ------------- -- -------------
-- 0 Init 0 7 0 0
-- 1 OpenRead 0 3 0 0 0
-- 2 Integer 3 1 0 0
-- 3 SeekRowid 0 6 1 0İki önek de ifadeyi gerçekten çalıştırmaz; ifade bir sorguya dönüşür ve çalıştırılsaydı ne yapacağını anlatan satırlar döndürür. Belgeler burada önemli bir ayrıntının altını çizer: EXPLAIN yalnızca çalıştırma aşamasını etkiler, hazırlama (prepare) aşamasını etkilemez. Bazı PRAGMA komutları işini hazırlama sırasında yaptığından, önlerine EXPLAIN koysanız bile etkileri gerçekleşebilir. Bu yüzden PRAGMA'ları EXPLAIN ile denemekten kaçının; ayrıntılar için PRAGMA komutları yazısına bakın.
Örnek şema
Aşağıdaki örneklerin tamamı bu iki tablo üzerinde, SQLite 3.50.6 komut satırı aracında çalıştırıldı. Tablolar boş olsa da plan oluşturulabilir; planlayıcı istatistik yoksa tablo boyutları için varsayılan tahminler kullanır. Gerçek verinizde, özellikle ANALYZE çalıştırıldıktan sonra, bazı seçimler farklılaşabilir. Bir önceki bölümdeki bytecode listesi de bu şema üzerinde alındı; oradaki sayılar şemaya ve sürüme bağlıdır.
CREATE TABLE musteri(id INTEGER PRIMARY KEY, ad TEXT, sehir TEXT);
CREATE TABLE siparis(
id INTEGER PRIMARY KEY,
musteri_id INTEGER,
tarih TEXT,
tutar REAL,
durum TEXT
);SCAN ve SEARCH: tablo nasıl okunuyor?
Plan, sorguda okunan her tablo için SCAN veya SEARCH ile başlayan bir satır içerir. SCAN tam tarama demektir: tablonun bütün satırları ziyaret edilir. Bir indeksin sırasıyla bütün tabloyu dolaşmak da SCAN olarak raporlanır. SEARCH ise satırların yalnızca bir alt kümesine gidildiğini gösterir ve parantez içinde hangi koşulun arama anahtarı olarak kullanıldığını yazar.
EXPLAIN QUERY PLAN SELECT * FROM siparis WHERE musteri_id = 7;
-- çıktı:
-- QUERY PLAN
-- `--SCAN siparis
EXPLAIN QUERY PLAN SELECT * FROM siparis WHERE id = 7;
-- çıktı:
-- QUERY PLAN
-- `--SEARCH siparis USING INTEGER PRIMARY KEY (rowid=?)
EXPLAIN QUERY PLAN SELECT * FROM siparis WHERE id BETWEEN 10 AND 20;
-- çıktı:
-- QUERY PLAN
-- `--SEARCH siparis USING INTEGER PRIMARY KEY (rowid>? AND rowid<?)İlk sorguda musteri_id üzerinde indeks olmadığı için tablonun tamamı okunur. İkinci ve üçüncü sorgularda ise id sütunu INTEGER PRIMARY KEY olduğundan satırın gizli kimliği olan rowid ile aynı şeydir; tablo zaten bu değere göre sıralı bir B-ağacında durduğu için tek bir kayda veya bir aralığa doğrudan atlanabilir. Plandaki ? işaretleri, değerin kendisinin değil koşulun biçiminin gösterildiğini anlatır. Rowid'in nasıl çalıştığı PRIMARY KEY ve rowid yazısında anlatılıyor.
Şimdi müşteri sütununa bir indeks ekleyelim ve aynı sorguya tekrar bakalım:
CREATE INDEX siparis_musteri ON siparis(musteri_id);
EXPLAIN QUERY PLAN SELECT * FROM siparis WHERE musteri_id = 7;
-- çıktı:
-- QUERY PLAN
-- `--SEARCH siparis USING INDEX siparis_musteri (musteri_id=?)
EXPLAIN QUERY PLAN SELECT musteri_id FROM siparis WHERE musteri_id = 7;
-- çıktı:
-- QUERY PLAN
-- `--SEARCH siparis USING COVERING INDEX siparis_musteri (musteri_id=?)İlk planda USING INDEX ifadesi görünür: SQLite önce indekste musteri_id = 7 olan girdileri bulur, sonra her girdinin rowid'iyle asıl tabloya gidip satırın kalan sütunlarını okur. Yani her satır için iki ikili arama yapılır. İkinci sorguda yalnızca indeksin zaten içerdiği sütun istendiği için tabloya hiç gidilmez ve plan USING COVERING INDEX der. Belgelere göre kapsayan indeks, satır başına bir ikili aramayı ortadan kaldırdığı için bazı sorguları belirgin biçimde hızlandırabilir. İndekslerin nasıl tasarlanacağı SQLite indeks oluşturma yazısının konusudur.
Birleştirmelerde döngü sırası
SQLite bütün birleştirmeleri iç içe döngülerle uygular. Plan, her döngü için bir SCAN veya SEARCH satırı yazar ve satırların sırası iç içe geçme sırasını gösterir: en üstteki satır dış döngüdür, en alttaki iç döngü. Önemli olan, bu sıranın FROM yan tümcesindeki yazılış sırası olmak zorunda olmamasıdır; plan sorgunun nasıl yazıldığını değil nasıl çalıştırılacağını gösterir.
EXPLAIN QUERY PLAN
SELECT m.ad, s.tutar
FROM musteri m JOIN siparis s ON s.musteri_id = m.id
WHERE m.sehir = 'İzmir';
-- çıktı:
-- QUERY PLAN
-- |--SCAN m
-- `--SEARCH s USING INDEX siparis_musteri (musteri_id=?)Burada dış döngü musteri tablosunu baştan sona tarar, çünkü sehir sütununda indeks yoktur. Her müşteri için iç döngü, siparişleri siparis_musteri indeksiyle arar. İç döngünün SEARCH olması iyi haberdir; iç döngüde SCAN görmek ise genellikle her dış satır için bütün iç tablonun okunması anlamına gelir ve büyük tablolarda en pahalı desendir. Birleştirme türleri hakkında ayrıntı JOIN türleri yazısında bulunuyor.
USE TEMP B-TREE: sıralama için geçici yapı

Sorguda ORDER BY, GROUP BY veya DISTINCT varsa SQLite sonuçları ya uygun bir indeksin sırasından yararlanarak ya da geçici bir B-ağacı kurup orada sıralayarak üretir. İkinci durumda plana USE TEMP B-TREE FOR ORDER BY (veya GROUP BY, DISTINCT) satırı eklenir. Belgeler indeks kullanmanın sıralamadan neredeyse her zaman çok daha verimli olduğunu belirtir.
EXPLAIN QUERY PLAN SELECT * FROM siparis WHERE musteri_id = 7 ORDER BY tarih;
-- çıktı:
-- QUERY PLAN
-- |--SEARCH siparis USING INDEX siparis_musteri (musteri_id=?)
-- `--USE TEMP B-TREE FOR ORDER BY
CREATE INDEX siparis_musteri_tarih ON siparis(musteri_id, tarih);
EXPLAIN QUERY PLAN SELECT * FROM siparis WHERE musteri_id = 7 ORDER BY tarih;
-- çıktı:
-- QUERY PLAN
-- `--SEARCH siparis USING INDEX siparis_musteri_tarih (musteri_id=?)İlk planda arama indeksle yapılıyor ama eşleşen satırlar tarihe göre sıralı gelmediği için ayrıca sıralanıyor. (musteri_id, tarih) indeksinde ise aynı müşterinin girdileri zaten tarihe göre dizilidir; geçici B-ağacı satırı kaybolur. Çok sütunlu bir indeksin hem aramayı hem sıralamayı karşılayabilmesi için eşitlikle aranan sütunların önce, sıralanan sütunun sonra gelmesi gerekir.
OR koşulları ve MULTI-INDEX OR
AND ile bağlanan terimler ayrı ayrı değerlendirilirken OR ile bağlanan koşullar tek bir terim gibi ele alınır. Her iki tarafı da bir indeksle karşılanabiliyorsa SQLite her taraf için ayrı arama yapıp sonuçların birleşimini alabilir; buna OR optimizasyonu denir.
EXPLAIN QUERY PLAN SELECT * FROM siparis WHERE musteri_id = 7 OR durum = 'iade';
-- çıktı:
-- QUERY PLAN
-- `--SCAN siparis
CREATE INDEX siparis_durum ON siparis(durum);
EXPLAIN QUERY PLAN SELECT * FROM siparis WHERE musteri_id = 7 OR durum = 'iade';
-- çıktı:
-- QUERY PLAN
-- `--MULTI-INDEX OR
-- |--INDEX 1
-- | `--SEARCH siparis USING INDEX siparis_musteri (musteri_id=?)
-- `--INDEX 2
-- `--SEARCH siparis USING INDEX siparis_durum (durum=?)İndeks yalnızca bir tarafta varken koşulun tamamı için tablo taranır, çünkü diğer tarafı karşılamak için zaten her satıra bakmak gerekir. İkinci indeks eklendiğinde plan iki ayrı arama ve bunların birleşimi hâline gelir. Belgedeki örneklerde alt satırlar INDEX 1, INDEX 2 etiketleri olmadan gösterilir; çıktı biçiminin sürüme göre değiştiğini burada da görebilirsiniz.
Alt sorgular, co-routine ve geçici tablolar
Alt sorgular planda dış sorgunun çocukları olarak görünür. SCALAR SUBQUERY tek değer döndüren bir alt sorgudur; başında CORRELATED varsa değeri dış sorgunun o anki satırına bağlıdır ve her dış satır için yeniden çalıştırılır. Bağıntısız bir skaler alt sorgu ise bir kez hesaplanıp tekrar kullanılabilir. IN (SELECT ...) biçimindeki alt sorgular LIST SUBQUERY olarak görünür.
EXPLAIN QUERY PLAN
SELECT ad, (SELECT count(*) FROM siparis s WHERE s.musteri_id = m.id)
FROM musteri m;
-- çıktı:
-- QUERY PLAN
-- |--SCAN m
-- `--CORRELATED SCALAR SUBQUERY 1
-- `--SEARCH s USING COVERING INDEX siparis_musteri (musteri_id=?)
EXPLAIN QUERY PLAN
SELECT * FROM musteri WHERE id IN (SELECT musteri_id FROM siparis WHERE tutar > 100);
-- çıktı:
-- QUERY PLAN
-- |--SEARCH musteri USING INTEGER PRIMARY KEY (rowid=?)
-- `--LIST SUBQUERY 1
-- |--SCAN siparis
-- `--CREATE BLOOM FILTERİkinci örnekte alt sorgu sipariş tablosunu bir kez tarayıp sonucu bir listeye koyuyor, dış sorgu da her değer için müşteriyi rowid ile buluyor. CREATE BLOOM FILTER ve birleştirmelerde görülebilen BLOOM FILTER ON satırları, planlayıcının gereksiz aramaları elemek için kurduğu yardımcı bir yapıyı gösterir. FROM içindeki alt sorgular için belgeler üç olasılık tanımlar: alt sorgu dış sorguyla birleştirilir (flattening) ve planda ayrı satır olarak görünmez; CO-ROUTINE olarak, dış sorgu satır istedikçe çalıştırılır; ya da birden fazla kez okunacaksa MATERIALIZE ile geçici bir tabloya yazılır. UNION, EXCEPT ve INTERSECT gibi bileşik sorgularda her parça ayrı satır alır ve plan COMPOUND QUERY veya MERGE başlığı altında toplanır. WITH ile yazılan sorguların nasıl planlandığı için CTE yazısına bakabilirsiniz.
İndeksi kullanılamaz kılan yazımlar
Bir terimin indeksle karşılanabilmesi için genellikle sütunun kendisinin bir karşılaştırma işlecinin bir tarafında yalın olarak durması gerekir: sutun = ifade, sutun > ifade, sutun IN (...), sutun IS NULL gibi. Sütunu bir fonksiyona veya aritmetik işleme soktuğunuzda planlayıcı artık o indeksi kullanamaz:
EXPLAIN QUERY PLAN SELECT * FROM siparis WHERE substr(tarih, 1, 4) = '2026';
-- çıktı:
-- QUERY PLAN
-- `--SCAN siparis
EXPLAIN QUERY PLAN SELECT * FROM siparis WHERE musteri_id + 0 = 7;
-- çıktı:
-- QUERY PLAN
-- `--SCAN siparisİlk sorgu için iki çözüm vardır: koşulu aralık olarak yazmak (tarih >= '2026-01-01' AND tarih < '2027-01-01') ya da ifadenin kendisine bir indeks tanımlamak. İfade indeksleri ve kısmi indeksler partial index ve ifade indeksi yazısında anlatılıyor. İkinci sorgudaki + 0 gibi yazımlar bazen bilerek, bir indeksi devre dışı bırakmak için kullanılır; bu son çare tekniğini ANALYZE yazısında ele alıyoruz.
Komut satırında .eqp ve .explain
Her sorgunun önüne elle önek yazmak yerine komut satırı aracını otomatik plan moduna alabilirsiniz. .eqp on açıkken araç girdiğiniz her ifade için önce ayrı bir EXPLAIN QUERY PLAN çalıştırır, planı yazar, sonra ifadenin kendisini çalıştırır. .eqp off bu modu kapatır.
.eqp on
SELECT count(*) FROM siparis WHERE durum = 'iade';
-- çıktı:
-- QUERY PLAN
-- `--SEARCH siparis USING COVERING INDEX siparis_durum (durum=?)
-- 0
.eqp off
.explain off
EXPLAIN QUERY PLAN SELECT * FROM siparis WHERE durum = 'iade';
-- çıktı: 3|0|62|SEARCH siparis USING INDEX siparis_durum (durum=?)Ağaç görünümü aslında komut satırının bir sunumudur. Ham hâlinde plan dört sütunlu bir tablodur: düğüm numarası, üst düğümün numarası, belgelerde şu an kullanılmadığı belirtilen yardımcı bir tamsayı ve açıklama metni. .explain off ağaç çizimini kapatıp bu satırları gösterir, .explain auto eski hâline döndürür. Yukarıdaki numaralar sürüme göre farklı olabilir; önemli olan son sütundur. Programlama dili bağlayıcılarından plan sorgularsanız da bu dört sütunu alırsınız.
.expert ile indeks önerisi almak
Komut satırı aracındaki .expert komutu, ardından yazdığınız tek bir sorgu için hangi indeksin işe yarayacağını önerir ve o indeks var olsaydı planın nasıl görüneceğini gösterir. Belgeler bu komutu deneysel olarak işaretler; ileride kaldırılabilir veya arayüzü değişebilir. Önerilen indeks adları rastgele bir son ek içerir, bu yüzden sizin ekranınızda farklı görünecektir.
CREATE TABLE siparis(id INTEGER PRIMARY KEY, musteri_id INTEGER, tarih TEXT, tutar REAL, durum TEXT);
.expert
SELECT * FROM siparis WHERE musteri_id = 7 AND tarih >= '2026-01-01';
-- çıktı:
-- CREATE INDEX siparis_idx_fb498759 ON siparis(musteri_id, tarih);
--
-- SEARCH siparis USING INDEX siparis_idx_fb498759 (musteri_id=? AND tarih>?)
CREATE INDEX siparis_mt ON siparis(musteri_id, tarih);
.expert
SELECT * FROM siparis WHERE musteri_id = 7 AND tarih >= '2026-01-01';
-- çıktı:
-- (no new indexes)
--
-- SEARCH siparis USING INDEX siparis_mt (musteri_id=? AND tarih>?)Uygun bir indeks zaten varsa araç (no new indexes) yazar ve mevcut planı gösterir. --sample YÜZDE seçeneği, önerileri verinin belirli bir yüzdesinden toplanan dağılım istatistiklerine dayandırır; varsayılan 0 değeri yalnızca şemaya ve sorguya bakar. Belgeler küçük veritabanları için --sample 100 kullanmamak için genellikle bir neden olmadığını, büyük tablolarda ise bu toplamanın pahalı olabileceğini belirtir. Öneriyi körü körüne uygulamayın: her indeks yazma işlemlerini yavaşlatır ve disk kaplar.
Plan satırları için hızlı başvuru

| Plan metni | Ne anlatır |
|---|---|
| SCAN tablo | Tablonun tüm satırları okunur |
| SCAN tablo USING INDEX i | Tablo, indeksin sırasıyla baştan sona dolaşılır |
| SEARCH tablo USING INTEGER PRIMARY KEY (rowid=?) | Satır doğrudan rowid ile bulunur |
| SEARCH tablo USING INDEX i (a=?) | İndeksle arama, sonra tabloya ek erişim |
| USING COVERING INDEX | Gereken her sütun indekste; tabloya gidilmez |
| USING AUTOMATIC COVERING INDEX | Yalnızca bu sorgu için geçici indeks kuruldu |
| USE TEMP B-TREE FOR ORDER BY | Sonuç ayrıca sıralanıyor |
| MULTI-INDEX OR | OR'un her tarafı ayrı indeksle aranıyor |
| CORRELATED SCALAR SUBQUERY | Alt sorgu her dış satır için tekrar çalışıyor |
| CO-ROUTINE / MATERIALIZE | FROM alt sorgusu akış olarak veya geçici tabloya yazılarak işleniyor |
Uygulamalı örnek: yavaş bir listeleme sorgusunu düzeltmek
Bir web uygulamasında kullanıcının son 20 giriş olayını gösteren bir sayfa düşünün. Tabloda indeks yokken sorgu her açılışta bütün olay tablosunu tarar ve ardından sonuçları sıralar. Aşağıda aynı sorgunun üç farklı indeks durumundaki planını görüyorsunuz:
CREATE TABLE olay(id INTEGER PRIMARY KEY, kullanici_id INTEGER, tur TEXT, zaman TEXT, ayrinti TEXT);
EXPLAIN QUERY PLAN
SELECT zaman, ayrinti FROM olay
WHERE kullanici_id = 42 AND tur = 'giris'
ORDER BY zaman DESC LIMIT 20;
-- çıktı:
-- QUERY PLAN
-- |--SCAN olay
-- `--USE TEMP B-TREE FOR ORDER BY
CREATE INDEX olay_kullanici ON olay(kullanici_id);
-- aynı sorgu:
-- QUERY PLAN
-- |--SEARCH olay USING INDEX olay_kullanici (kullanici_id=?)
-- `--USE TEMP B-TREE FOR ORDER BY
DROP INDEX olay_kullanici;
CREATE INDEX olay_kul_tur_zaman ON olay(kullanici_id, tur, zaman);
-- aynı sorgu:
-- QUERY PLAN
-- `--SEARCH olay USING INDEX olay_kul_tur_zaman (kullanici_id=? AND tur=?)Yalnızca kullanici_id üzerindeki indeks taramayı aramaya çevirir ama sıralama hâlâ geçici bir B-ağacında yapılır ve tur koşulu her satır için ayrıca sınanır. Üç sütunlu indeks ise iki eşitlik koşulunu karşılar ve satırları zaten zamana göre dizili verir; DESC sıralama için indeks geriye doğru okunabilir ve LIMIT 20 sayesinde ilk 20 girdide durulabilir. Aynı indeksle ilgili üç gözlem daha yapalım:
EXPLAIN QUERY PLAN
SELECT zaman FROM olay WHERE kullanici_id = 42 AND tur = 'giris' ORDER BY zaman DESC LIMIT 20;
-- çıktı:
-- QUERY PLAN
-- `--SEARCH olay USING COVERING INDEX olay_kul_tur_zaman (kullanici_id=? AND tur=?)
EXPLAIN QUERY PLAN SELECT zaman FROM olay WHERE tur = 'giris';
-- çıktı:
-- QUERY PLAN
-- `--SCAN olay USING COVERING INDEX olay_kul_tur_zaman
EXPLAIN QUERY PLAN SELECT zaman FROM olay WHERE kullanici_id = 42 AND zaman > '2026-11-01';
-- çıktı:
-- QUERY PLAN
-- `--SEARCH olay USING COVERING INDEX olay_kul_tur_zaman (kullanici_id=?)İstenen sütunlar indekste bulunduğunda plan kapsayan indekse döner. Yalnızca ikinci sütunla filtrelendiğinde indeksin en soldaki sütunu kısıtlanmadığı için arama yapılamaz; burada indeks yalnızca tablodan daha küçük olduğu için tarama amacıyla kullanılır. Son sorguda ise tur sütunu atlandığından, zaman koşulu indeksle daraltmaya katılamaz: planda yalnızca (kullanici_id=?) görünür. Belgelerdeki kural şudur: indeks sütunları soldan sağa boşluksuz kullanılmalı, eşitlik veya IN ile kısıtlanan sütunlardan sonra yalnızca en sağdaki sütunda aralık koşulu olabilir.
Sık yapılan hatalar
- Boş test veritabanında karar vermek: Plan veriye ve istatistiklere bağlıdır. Gerçeğe yakın veri yüklemeden ve
PRAGMA optimizeçalıştırmadan çıkan plan canlı ortamdakiyle aynı olmayabilir. - Her SCAN satırını sorun saymak: Birkaç yüz satırlık bir tabloyu taramak ucuzdur; asıl dikkat edilecek yer büyük tabloların iç döngüde taranmasıdır.
- Sütunu fonksiyona sokmak:
lower(eposta) = ?gibi bir koşul düz bir indeksi kullanamaz; ya ifade indeksi tanımlayın ya da veriyi normalize edilmiş biçimde saklayın. - Sütun sırası yanlış çok sütunlu indeks: Aralık veya sıralama sütununu eşitlik sütunlarının önüne koymak, indeksin yalnızca bir kısmının kullanılmasına yol açar.
- Çıktıyı kodda ayrıştırmak: Metin biçimi sürümler arasında değişti ve değişmeye devam edebilir.
Sık Sorulan Sorular
EXPLAIN QUERY PLAN sorguyu çalıştırır mı?
Hayır. Yalnızca planı döndürür; INSERT, UPDATE veya DELETE önüne yazıldığında da veri değişmez. Belgelerdeki tek istisna, işini hazırlama aşamasında yapan bazı PRAGMA komutlarıdır.
UPDATE ve DELETE için de plan alabilir miyim?
Evet. Komut en çok SELECT için yararlıdır ama tablo okuyan UPDATE, DELETE ve INSERT INTO ... SELECT ifadeleri için de plan gösterir. Bir UPDATE'in WHERE koşulunun indeks kullanıp kullanmadığını böyle kontrol edebilirsiniz.
Planda indeks görünüyor ama sorgu hâlâ yavaş, neden?
İndeks seçici olmayabilir; örneğin yalnızca iki farklı değer alan bir sütundaki indeks satırların yarısını döndürür. Ayrıca sıralama için geçici B-ağacı veya iç döngüde tarama olup olmadığına bakın. Planlayıcının seçicilik bilgisini nereden aldığını ANALYZE yazısında anlatıyoruz.
Sorgunun ne kadar sürdüğünü nasıl ölçerim?
Komut satırında .timer on her ifadeden sonra geçen süreyi yazar. Ölçüm ve genel ayarlar için SQLite performans ayarları yazısına, genel sorgu iyileştirme ilkeleri için SQL sorgu optimizasyonu rehberimize bakın.
Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.
İlgili içerikler: SQLite öğrenme rehberi · SQLite ANALYZE ve sorgu planlayıcı · SQLite indeks oluşturma · SQLite partial index ve ifade indeksi · SQLite performans ayarları · SQL sorgu optimizasyonu