2010-11-10 4 views
7

Une base de données (simplifiée) de signets Internet. Je pensais que ce serait judicieux d'organiser les tables logiquement, comme ceci:Une manière optimale de joindre trois tables dans SQLite

Bookmarks (id, title, url; basically external data) 
+------+------------+-----+ 
| suid | Title | ... | 
+------+------------+-----+ 

User (user-specific data: favorites, ratings, etc) 
+------+------------+-----+ 
| suid | IsFavorite | ... | 
+  + (0 or 1) +  + 
+------+------------+-----+ 

History (last used, use count etc) 
+------+------------+-----+ 
| suid | LastUsed | ... | 
+  +(TDateTime) +  + 
+------+------------+-----+ 

(« suid » est l'ID unique, entier clé primaire)

À partir des signets marqués comme préféré que je dois sélectionner N récemment utilisé (pour remplir un menu lors de l'exécution pour plus de commodité). L'instruction fonctionne et semble suffisamment lisible, mais est-elle optimale?

SELECT Bookmarks.suid, Title from Bookmarks 
    INNER JOIN User USING (suid) 
    INNER JOIN History USING (suid) 
    WHERE IsFavorite = 1 
    ORDER BY LastUsed DESC 
    LIMIT 15; 

La table Bookmarks est destinée à contenir en moyenne 20 à 50 000 enregistrements (c'est-à-dire, pas votre gestionnaire de favoris de navigateur standard :-) L'application va exécuter 3 ou 4 instructions similaires au démarrage pour remplir les contrôles. Tous les champs utilisés dans l'exemple sont indexés.

Je m'apprends le langage SQL et j'ai trouvé le code ci-dessus, mais peut-être que je suis en train de négliger une syntaxe ou un idiome qui pourrait l'améliorer?

+0

Si l'indicateur favori est stocké dans la table des utilisateurs, cela signifie que tous les signets associés à l'utilisateur sont favoris - il doit être au niveau du signet, sinon je ne comprends pas le but. –

+0

J'ai tendance à trop expliquer dans mes questions, donc j'ai concocté un simple exemple simple pour éviter cela. La table des favoris principale sera mise à jour périodiquement. Au cours de la mise à jour, je ne veux pas toucher à des données que les utilisateurs ont saisies, comme la notation, le marquage comme favoris, etc. Il semblait plus propre à séparer les deux. De même, certains utilisateurs peuvent ne pas vouloir conserver l'historique, auquel cas l'application peut simplement effacer ou supprimer toute la table d'historique. (Ou, peut-être que le nom «Utilisateurs» est trompeur: il ne s'agit pas d'une table pour les données de compte utilisateur, mais pour les points de données saisis par les utilisateurs, c'est une application de bureau pour utilisateur unique). –

Répondre

4

Il est impossible (ou du moins très, très difficile) de deviner à partir de SQL brut exactement comment le moteur de base de données va répondre à la requête. Pour cette raison, vous devez utiliser EXPLAIN pour découvrir comment SQLite va réellement obtenir les données. Et sachez que le plan d'exécution qu'il génère sera différent en fonction de la quantité de données dans chaque table et de ce à quoi les données "ressemblent" (en termes de nombre de valeurs différentes trouvées dans les colonnes indexées). Assurez-vous donc d'amorcer votre base de données de test avec des données réalistes.

Une fois que vous essayez EXPLAIN, je pense qu'il y a une possibilité que vous trouviez que SQLite rejoint les tables ensemble avant de prendre les 15 premières correspondances, ce qui serait non-optimal si c'est vrai. Si cela se révèle être le cas, vous pouvez essayer quelque chose comme:

SELECT Bookmarks.suid, Title from Bookmarks 
    INNER JOIN User USING (suid) 
    WHERE IsFavorite = 1 
    AND suid IN (SELECT suid FROM History ORDER BY LastUsed DESC LIMIT 15); 

Mais, encore une fois, ne pas essayer que jusqu'à ce que vous avez vu de EXPLIQUEZ que SQLite reçoit les données d'une manière non optimale .

0

Cela me semble correct. Vous le savez peut-être déjà, mais vous pouvez étudier votre requête en utilisant le mot-clé explain (http://www.sqlite.org/lang_explain.html) si vous souhaitez l'affiner davantage.

À la votre!

0

Vous pouvez utiliser le mot-clé EXPLAIN comme déjà dit, mais il existe d'autres façons de l'améliorer. Il y a un site web avec quelques infos ... jetez un coup d'œil sur 'here pour en savoir plus ... bonne chance!