2009-10-13 10 views
6

Je m'attendais à passer des fichiers ms-access aux fichiers SQLite pour mes besoins de base de données simples; pour les raisons habituelles: taille de fichier plus petite, moins de frais généraux, open source, etc.Comment accélérer la requête avec plusieurs INNER JOINs

Une chose qui m'empêche de faire le changement est ce qui semble être un manque de vitesse dans SQLite. Pour les requêtes SELECT simples, SQLite semble fonctionner aussi bien, ou mieux que MS-Access. Le problème se produit avec une requête SELECT assez complexe avec de multiples déclarations INNER JOIN:

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')) 

Dans MS-Access, cette requête exécute environ 2,5 secondes. En SQLite, il faut un peu plus de 8 minutes. Cela prend autant de temps si j'exécute la requête à partir du code VB ou à partir de l'invite de commande à l'aide de sqlite3.exe.

Mes questions sont les suivantes:

  1. est-SQLite tout simplement pas optimisé pour gérer plusieurs déclarations INNER JOIN?
  2. Ai-je fait quelque chose de manifestement stupide dans ma requête (parce que je suis nouveau à SQLite) qui le rend si lent?

Et avant que quiconque suggère une technologie complètement différente, non je ne peux pas changer. Mes choix sont MS-Access ou SQLite. :)

UPDATE: Affectation d'un index pour chacune des colonnes de la base de données SQLite réduit le temps de recherche de plus de 8 minutes jusqu'à environ 6 secondes. Merci à Larry Lustig pour expliquer pourquoi l'INDEXing était nécessaire.

+3

Utilisez-vous des INDEX? –

+0

@Phill Pafford: Je n'utilise pas d'index sur les données MS-Access ou SQLite. J'essaie de comparer l'accès à sqlite donc j'ai laissé la même structure de données dans les deux. – Stewbob

+9

Impossible de poster une réponse, donc d'essayer un commentaire: MS Access est très agressif sur l'indexation des colonnes en votre nom, alors que SQLite vous demandera de créer explicitement les index dont vous avez besoin. Ainsi, il est possible qu'Access ait indexé [Description] ou [D] pour vous mais que ces index sont manquants dans SQLite. Je n'ai pas d'expérience avec cette quantité d'activité JOIN dans SQLite. Je l'ai utilisé dans un projet Django avec une quantité relativement faible de données et je n'ai détecté aucun problème de performance. –

Répondre

11

Comme l'a demandé, je suis reposter mon commentaire précédent comme une réponse réelle (quand je posté le commentaire Je n'ai pas pu, pour une raison quelconque, l'afficher comme une réponse):

MS Access est très agressif sur l'indexation des colonnes en votre nom, alors que SQLite vous demandera de créer explicitement les index dont vous avez besoin. Ainsi, il est possible qu'Access ait indexé [Description] ou [D] pour vous mais que ces index sont manquants dans SQLite. Je n'ai pas d'expérience avec cette quantité d'activité JOIN dans SQLite. Je l'ai utilisé dans un projet Django avec une quantité relativement faible de données et je n'ai détecté aucun problème de performance.

6

Avez-vous des problèmes d'intégrité référentielle? Je demande parce ai l'impression que vous avez rejoint inutiles, donc je re-écrit votre requête comme:

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: Merci pour votre version nettoyée de la requête. Je suis retourné et j'ai regardé ma requête, et il s'est avéré que j'avais omis plusieurs déclarations WHERE, alors oui, j'avais besoin de tous les JOINs. J'ai encore appris quelques choses utiles de votre réponse. MERCI! – Stewbob

+0

Stewbob - si c'est bien la réponse, vous devez le marquer comme tel afin que rexem obtienne les points. Il a fait du bon travail pour livrer cette solution! –

+0

@Mark: Selon les commentaires, Larry Lustig a fourni la réponse mais n'est pas revenu pour l'afficher comme réponse pour obtenir un crédit. –

0

Si DESCRIPTIONS et tbl_D_E ont plusieurs balayages de lignes, alors oCode et D doivent être indexés. Regardez l'exemple ici pour voir comment indexer et dire combien de balayages de lignes il y a (http://www.siteconsortium.com/h/p1.php?id=mysql002).

Cela pourrait corriger si ..

CREATE INDEX ocode_index SUR DESCRIPTIONS (oCODE) AU MOYEN BTREE; CREATE INDEX d_index ON tbl_D_E (D) UTILISATION DE BTREE;

etc ....

L'indexation est correctement un morceau du puzzle qui peut facilement doubler, tripler ou plus la vitesse de la requête.