Ho un database sqlite con due tabelle, ognuna con 50.000 righe, contenente nomi di persone (false). Ho creato una semplice query per scoprire quanti nomi ci sono (nome, medio iniziale, cognome) comuni a entrambe le tabelle:
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;
Quando non ci sono indici ad eccezione delle chiavi primarie (irrilevanti per questa query), viene eseguito rapidamente:
[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
Ma se aggiungo indici alle tre colonne su ogni tabella (sei indici in tutto):
CREATE INDEX `idx_uk_givenname` ON `fakenames_uk` (`givenname` )
//etc.
quindi corre dolorosamente lentamente:
[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
C'è qualche rima o ragione per questo?
Ecco il risultato di EXPLAIN QUERY PLAN
per la versione senza indici:
0|0|0|SCAN TABLE fakenames_uk
0|1|1|SEARCH TABLE fakenames_usa USING AUTOMATIC COVERING INDEX (middleinitial=? AND surname=? AND givenname=?)
Questo è con gli indici:
0|0|0|SCAN TABLE fakenames_uk
0|1|1|SEARCH TABLE fakenames_usa USING INDEX idx_us_middleinitial (middleinitial=?)
SELECT c FROM t WHERE a=1 AND b=2
, l'indice t(a,b,c)
copre ma t(a,b)
non lo è. Il vantaggio degli indici di copertura è che l'intero risultato della query può essere estratto direttamente dall'indice, mentre gli indici non di copertura trovano rapidamente le righe pertinenti ma devono comunque fare riferimento ai dati della tabella principale per selezionare i valori.
middleinitial
,surname
egivenname
)?