2009-10-13 11 views
6

He estado jugando con el cambio de archivos ms-access a archivos SQLite para mis necesidades simples de base de datos; por las razones usuales: tamaño de archivo más pequeño, menos sobrecarga, código abierto, etc.Cómo acelerar la consulta con múltiples INNER JOINs

Una cosa que me está impidiendo hacer el cambio es lo que parece ser una falta de velocidad en SQLite. Para consultas SELECT simples, SQLite parece funcionar tan bien o mejor que MS-Access. El problema se produce con una consulta SELECT bastante compleja con múltiples declaraciones combinación interna:

SELECT DISTINCT 
     DESCRIPTIONS.[oCode] AS OptionCode, 
     DESCRIPTIONS.[descShort] AS OptionDescription 
FROM DESCRIPTIONS 
INNER JOIN tbl_D_E ON DESCRIPTIONS.[oCode] = tbl_D_E.[D] 
INNER JOIN tbl_D_F ON DESCRIPTIONS.[oCode] = tbl_D_F.[D] 
INNER JOIN tbl_D_H ON DESCRIPTIONS.[oCode] = tbl_D_H.[D] 
INNER JOIN tbl_D_J ON DESCRIPTIONS.[oCode] = tbl_D_J.[D] 
INNER JOIN tbl_D_T ON DESCRIPTIONS.[oCode] = tbl_D_T.[D] 
INNER JOIN tbl_Y_D ON DESCRIPTIONS.[oCode] = tbl_Y_D.[D] 
WHERE ((tbl_D_E.[E] LIKE '%') 
     AND (tbl_D_H.[oType] ='STANDARD') 
     AND (tbl_D_J.[oType] ='STANDARD') 
     AND (tbl_Y_D.[Y] = '41') 
     AND (tbl_Y_D.[oType] ='STANDARD') 
     AND (DESCRIPTIONS.[oMod]='D')) 

En MS-Access, esta consulta se ejecuta en unos 2,5 segundos. En SQLite, toma un poco más de 8 minutos. Lleva la misma cantidad de tiempo si estoy ejecutando la consulta desde el código VB o desde el símbolo del sistema usando sqlite3.exe.

Así que mis preguntas son las siguientes:

  1. Es SQLite no optimizado para manejar múltiples cuentas combinación interna?
  2. ¿He hecho algo obviamente estúpido en mi consulta (porque soy nuevo en SQLite) que lo hace tan lento?

Y antes de que nadie sugiera una tecnología completamente diferente, no, no puedo cambiar. Mis opciones son MS-Access o SQLite. :)

UPDATE: Asignación de un índice para cada una de las columnas en la base de datos SQLite redujo el tiempo de consulta de más de 8 minutos hasta aproximadamente 6 segundos. Gracias a Larry Lustig para explicar por qué se necesitaba el INDEXing.

+3

¿Estás usando ÍNDICES? –

+0

@Phill Pafford: No estoy usando índices ni en MS-Access ni en los datos de SQLite. Estoy tratando de comparar el acceso a sqlite, así que dejé la estructura de datos igual en ambos. – Stewbob

+9

No se pudo publicar una respuesta, por lo tanto, intentar un comentario: MS Access es muy agresivo con la indexación de columnas en su nombre, mientras que SQLite le pedirá que cree explícitamente los índices que necesita. Por lo tanto, es posible que Access haya indexado [Descripción] o [D] por usted, pero que esos índices falten en SQLite. No tengo experiencia con esa cantidad de actividad JOIN en SQLite. Lo usé en un proyecto de Django con una cantidad relativamente pequeña de datos y no detecté ningún problema de rendimiento. –

Respuesta

11

Conforme a lo solicitado, estoy volver a colocar mi comentario anterior como una respuesta real (cuando por primera vez publicó el comentario No pude, por algún motivo, publicarlo como respuesta):

MS Access es muy agresivo con la indexación de columnas en su nombre, mientras que SQLite le pedirá que cree explícitamente los índices que necesita. Por lo tanto, es posible que Access haya indexado [Descripción] o [D] por usted, pero que esos índices falten en SQLite. No tengo experiencia con esa cantidad de actividad JOIN en SQLite. Lo usé en un proyecto de Django con una cantidad relativamente pequeña de datos y no detecté ningún problema de rendimiento.

6

¿Tiene problemas con la integridad de las referencias? Lo pregunto porque tengo la impresión de que tienes innecesaria une, por lo que re-escribió la consulta como:

SELECT DISTINCT 
     t.[oCode] AS OptionCode, 
     t.[descShort] AS OptionDescription 
    FROM DESCRIPTIONS t 
    JOIN tbl_D_H h ON h.[D] = t.[oCode] 
       AND h.[oType] = 'STANDARD' 
    JOIN tbl_D_J j ON j.[D] = t.[oCode] 
       AND j.[oType] = 'STANDARD' 
    JOIN tbl_Y_D d ON d.[D] = t.[oCode] 
       AND d.[Y] = '41' 
       AND d.[oType] ='STANDARD' 
WHERE t.[oMod] = 'D' 
+0

@rexem: Gracias por limpiar la versión de la consulta. Volví y miré mi consulta, y resultó que omití varias de las declaraciones WHERE, así que sí, necesitaba todas las UNIONES. Todavía aprendí algunas cosas útiles de tu respuesta. ¡GRACIAS! – Stewbob

+0

Stewbob: si esta es la respuesta, debe marcarla como tal para que rexem obtenga los puntos. ¡Hizo un buen trabajo para entregar esta solución! –

+0

@Mark: Según los comentarios, Larry Lustig proporcionó la respuesta, pero no ha vuelto a publicarla como respuesta para obtener crédito. –

0

Si las DESCRIPCIONES y tbl_D_E tienen múltiples escaneos de filas, entonces oCode y D deberían estar indexados. Mire el ejemplo aquí para ver cómo indexar y decir cuántos escaneos de filas hay (http://www.siteconsortium.com/h/p1.php?id=mysql002).

Esto podría solucionarlo, aunque ..

CREATE INDEX ocode_index en descripciones (OCODE) utilizando BTREE; CREAR INDICE d_index ON tbl_D_E (D) USANDO BTREE;

etc ....

de indexación correctamente es una pieza del rompecabezas que puede fácilmente doble, triple o más la velocidad de la consulta.

Cuestiones relacionadas