Je souhaite implémenter une fonctionnalité très courante: filtrer certains éléments par tag. Il existe de nombreux tutoriels sur Internet avec des exemples de la façon de le faire. La requête est assez simple et rapide (en supposant que les index appropriés existent).
Mais généralement les éléments filtrés doivent être triés par un champ. Par exemple, lorsque vous filtrez les questions par tag sur SO, les résultats sont triés.Trier les éléments filtrés par le tag
Pour accomplir cette tâche (en supposant que nous devons trier par notes), on pourrait écrire:
SELECT item.id FROM item
INNER JOIN taggeditem ON taggeditem.item_id = item.id
WHERE
taggeditem.tag_id = 1234
ORDER BY item.rating DESC
Nous avons des indices (taggeditem.tag_id)
, (item.id)
, (item.rating
) Le problème avec cette requête est que MySQL ne peut pas utilisez index sur item.rating, car la clé utilisée pour récupérer les lignes n'est pas la même que celle utilisée dans ORDER BY (MySQL: ORDER BY Optimization). Cela conduit à utiliser une table temporaire et filesort, ce qui à son tour conduit à ralentir le temps d'exécution.
La solution que j'ai trouvée est de dénormaliser le champ de tri à la table taggeditem
, de sorte que je puisse créer l'index (tag_id, item_rating)
sur taggeditem
.
J'ai recherché des questions similaires chez SO, et trouvé seulement celui-ci: Mysql slow query: INNER JOIN + ORDER BY causes filesort. La solution était la même.
Donc, je veux demander, est-ce une solution commune à ce problème? Est-ce une bonne pratique de dénormaliser un tas de champs de tri à taggeditem, comme créé, rating? Au SO, vous pouvez trier en utilisant 4 paramètres différents (plus récent, chaud, votes, actif) - cela signifie-t-il qu'ils ont dénormalisé les champs qui sont utilisés pour trier les résultats? Y a-t-il des alternatives à cette solution?
est un article ou un article? confus ... vous pourriez vouloir re-vérifier le SQL – ajreal
J'ai édité le SQL, je voulais dire l'article de la table bien sûr –