Tengo una base de datos sqlite con dos tablas, cada una con 50,000 filas, que contiene nombres de personas (falsas). He construido una consulta simple para averiguar cuántos nombres hay (nombre de pila, inicial del segundo nombre, apellido) que son comunes a ambas tablas:
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;
Cuando no hay índices excepto en las claves primarias (irrelevantes para esta consulta), se ejecuta rápidamente:
[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
Pero si agrego índices a las tres columnas en cada tabla (seis índices en total):
CREATE INDEX `idx_uk_givenname` ON `fakenames_uk` (`givenname` )
//etc.
entonces corre dolorosamente lento:
[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
¿Hay alguna rima o razón para esto?
Aquí está el resultado de EXPLAIN QUERY PLAN
la versión sin índices:
0|0|0|SCAN TABLE fakenames_uk
0|1|1|SEARCH TABLE fakenames_usa USING AUTOMATIC COVERING INDEX (middleinitial=? AND surname=? AND givenname=?)
Esto es con índices:
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
, el índice t(a,b,c)
está cubriendo pero t(a,b)
no. El beneficio de los índices de cobertura es que todo el resultado de la consulta se puede extraer directamente del índice, mientras que los índices de no cobertura encuentran rápidamente las filas relevantes, pero aún necesita referirse a los datos de la tabla principal para seleccionar los valores.
middleinitial
,surname
ygivenname
)?