Saya memiliki database sqlite dengan dua tabel, masing-masing dengan 50.000 baris, berisi nama-nama orang (palsu). Saya telah membuat kueri sederhana untuk mengetahui berapa banyak nama yang ada (nama yang diberikan, nama tengah, nama keluarga) yang umum untuk kedua tabel:
select count(*) from fakenames_uk inner join fakenames_usa on fakenames_uk.givenname=fakenames_usa.givenname and fakenames_uk.surname=fakenames_usa.surname and fakenames_uk.middleinitial=fakenames_usa.middleinitial;
Ketika tidak ada indeks kecuali pada kunci utama (tidak relevan dengan permintaan ini), itu berjalan dengan cepat:
[james@marlon Downloads] $ time sqlite3 generic_data_no_indexes.sqlite "select count(*) from fakenames_uk inner join fakenames_usa on fakenames_uk.givenname=fakenames_usa.givenname and fakenames_uk.surname=fakenames_usa.surname and fakenames_uk.middleinitial=fakenames_usa.middleinitial;"
131
real 0m0.115s
user 0m0.111s
sys 0m0.004s
Tetapi jika saya menambahkan indeks ke tiga kolom pada setiap tabel (enam indeks semuanya):
CREATE INDEX `idx_uk_givenname` ON `fakenames_uk` (`givenname` )
//etc.
lalu berjalan dengan sangat lambat:
[james@marlon Downloads] $ time sqlite3 generic_data.sqlite "select count(*) from fakenames_uk inner join fakenames_usa on fakenames_uk.givenname=fakenames_usa.givenname and fakenames_uk.surname=fakenames_usa.surname and fakenames_uk.middleinitial=fakenames_usa.middleinitial;"
131
real 1m43.102s
user 0m52.397s
sys 0m50.696s
Apakah ada sajak atau alasan untuk ini?
Inilah hasil EXPLAIN QUERY PLAN
untuk versi tanpa indeks:
0|0|0|SCAN TABLE fakenames_uk
0|1|1|SEARCH TABLE fakenames_usa USING AUTOMATIC COVERING INDEX (middleinitial=? AND surname=? AND givenname=?)
Ini dengan indeks:
0|0|0|SCAN TABLE fakenames_uk
0|1|1|SEARCH TABLE fakenames_usa USING INDEX idx_us_middleinitial (middleinitial=?)
performance
index
optimization
sqlite
count
keamanan chiastic
sumber
sumber
middleinitial
,surname
dangivenname
)?SELECT c FROM t WHERE a=1 AND b=2
, indekst(a,b,c)
mencakup tetapit(a,b)
tidak. Manfaat dari indeks yang dicakup adalah bahwa seluruh hasil kueri dapat ditarik langsung dari indeks, sedangkan indeks yang tidak mencakup dengan cepat menemukan baris yang relevan tetapi masih perlu merujuk ke data tabel utama untuk memilih nilai-nilai.Jawaban:
Dalam SQLite, gabungan dieksekusi sebagai gabungan simpul bersarang, yaitu, basis data melewati satu tabel, dan untuk setiap baris, mencari baris yang cocok dari tabel lainnya.
Jika ada indeks, database dapat mencari setiap kecocokan dalam indeks dengan cepat, dan kemudian pergi ke baris tabel yang sesuai untuk mendapatkan nilai-nilai kolom lain yang diperlukan.
Dalam hal ini, ada tiga kemungkinan indeks. Tanpa informasi statistik (yang akan dibuat dengan menjalankan ANALYZE ), database memilih yang terkecil, untuk mengurangi I / O. Namun,
middleinitial
indeks tidak berguna karena tidak mengurangi jumlah baris tabel yang perlu diambil; dan langkah tambahan melalui indeks sebenarnya meningkatkan I / O yang dibutuhkan karena baris tabel tidak lagi dibaca secara berurutan, tetapi secara acak.Jika tidak ada indeks, pencarian baris yang cocok akan membutuhkan pemindaian tabel lengkap dari tabel kedua untuk setiap baris dari tabel pertama. Ini akan sangat buruk sehingga database memperkirakan bahwa itu bermanfaat untuk membuat dan kemudian menjatuhkan indeks sementara hanya untuk permintaan ini. Indeks sementara ("OTOMATIS") ini dibuat pada semua kolom yang digunakan untuk pencarian. Operasi COUNT (*) tidak memerlukan nilai dari kolom lain, jadi indeks ini merupakan indeks penutup , yang berarti tidak perlu mencari baris tabel yang terkait dengan entri indeks, yang bahkan lebih menghemat saya. /HAI.
Untuk mempercepat kueri ini, buat indeks ini secara permanen, sehingga tidak perlu lagi membuat yang sementara:
Indeks aktif
surname
tidak lagi diperlukan karena indeks tiga kolom dapat digunakan untuk pencarian apa pun di kolom ini.Indeks aktif
givenname
mungkin berguna jika Anda akan melakukan pencarian pada kolom ini saja.Indeks aktif
middleinitial
selalu tidak berharga: kueri yang mencari salah satu dari 26 nilai yang mungkin lebih cepat jika hanya memindai seluruh tabel.sumber