Quelle est la manière la plus efficace de stocker des balises dans une base de données?

138

J'implémente un système de balisage sur mon site Web similaire à celui utilisé par stackoverflow, ma question est la suivante: quel est le moyen le plus efficace de stocker des balises afin qu'elles puissent être recherchées et filtrées?

Mon idée est la suivante:

Table: Items
Columns: Item_ID, Title, Content

Table: Tags
Columns: Title, Item_ID

Est-ce trop lent? Y a-t-il un meilleur moyen?

Logan Serman
la source
2
Précédemment demandé: stackoverflow.com/questions/20856/…
DrBloodmoney
1
À partir de 2016, utilisez Solr ou Elasticsearch
Charles L.

Réponses:

189

Un élément aura plusieurs balises. Et une balise appartiendra à de nombreux articles. Cela implique pour moi que vous aurez très probablement besoin d'une table intermédiaire pour surmonter l'obstacle plusieurs à plusieurs.

Quelque chose comme:

Table:
Colonnes des éléments : ID_article, Titre_article, Contenu

Table: Tags
Colonnes: Tag_ID, Tag_Title

Table:
Colonnes Items_Tags: Item_ID, Tag_ID

Il se peut que votre application Web soit incroyablement populaire et ait besoin d'être dénormalisée plus tard, mais il est inutile de brouiller les eaux trop tôt.

Simon Scarfe
la source
s'il y a quelque chose comme tagGroup comment le gérer, par exemple les balises sont regroupées en catégories, par exemple: Langages de programmation: c #, vb, pearl. OS: windows7, dos, linux etc
Thunder
4
@Thunder: en supposant qu'une balise ne peut appartenir qu'à une seule catégorie, je créerais une table TagCategory composée de category_id et category_name. À partir de là, j'ajouterais un champ category_id à la table Tags et effectuerais une jointure à ce sujet.
Simon Scarfe
114

Vous devriez lire les articles de blog de Philipp Keller sur le marquage des schémas de base de données. Il en essaie quelques-uns et rapporte ses résultats, à la fois en termes de facilité de construction de requêtes communes et en termes de performances . Le nombre d'étiquettes, le nombre d'articles étiquetés et le nombre d'étiquettes par article étaient tous des facteurs. Les messages datent de 2005; Je ne suis au courant d'aucune mise à jour depuis lors.

Rob Kennedy
la source
19
Je pense que c'est la meilleure réponse. Il est basé sur des tests et des recherches réels plutôt que sur des suppositions comme la plupart des autres réponses.
Cristian Vrabie
4
Les liens dans la réponse ne semblent pas fonctionner. Trouvé une copie à vtidter.blogspot.be/2014/02/database-schema-for-tags.html
Christophe Herreman
8

En fait, je pense que la dénormalisation du tableau des balises pourrait être une meilleure façon d'avancer, en fonction de l'échelle.

De cette façon, la table des balises a simplement tagid, itemid, tagname.

Vous obtiendrez des noms de variables en double, mais cela rend l'ajout / la suppression / l'édition de balises pour des éléments spécifiques BEAUCOUP plus simple. Vous n'avez pas besoin de créer une nouvelle balise, de supprimer l'allocation de l'ancienne et d'en réattribuer une nouvelle, il vous suffit de modifier la variable.

Pour afficher une liste de balises, vous utilisez simplement DISTINCT ou GROUP BY, et bien sûr, vous pouvez également compter combien de fois une balise est utilisée facilement.

Neil Barnwell
la source
4

Si cela ne vous dérange pas d'utiliser un peu de choses non standard, Postgres version 9.4 et plus a une option de stockage d'un enregistrement de type tableau de texte JSON.

Votre schéma serait:

Table: Items
Columns: Item_ID:int, Title:text, Content:text

Table: Tags
Columns: Item_ID:int, Tag_Title:text[]

Pour plus d'informations, consultez cet excellent article de Josh Berkus: http://www.databasesoup.com/2015/01/tag-all-things.html

Il existe plus d'options différentes comparées à fond pour les performances et celle suggérée ci-dessus est la meilleure dans l'ensemble.

Dmitry Shvedov
la source
2

Je suggérerais d'utiliser une troisième table intermédiaire pour stocker les associations de balises <=> éléments, car nous avons des relations plusieurs-à-plusieurs entre les balises et les éléments, c'est-à-dire qu'un élément peut être associé à plusieurs balises et une balise peut être associée à plusieurs éléments. HTH, Valve.

Valentin Vasilyev
la source
1

Vous ne pouvez pas vraiment parler de lenteur sur la base des données que vous avez fournies dans une question. Et je ne pense pas que vous devriez même trop vous soucier des performances à ce stade de développement. C'est ce qu'on appelle l' optimisation prématurée .

Cependant, je suggère que vous incluiez la colonne Tag_ID dans la table Tags. Il est généralement recommandé que chaque table ait une colonne ID.

Rockcoder
la source
1

Si l'espace va être un problème, ayez une 3ème table Tags (Tag_Id, Title) pour stocker le texte de la balise, puis changez votre table Tags en (Tag_Id, Item_Id). Ces deux valeurs doivent également fournir une clé primaire composite unique.

Adam Pope
la source
0

Les éléments doivent avoir un champ «ID» et les balises doivent avoir un champ «ID» (Clé primaire, en cluster).

Ensuite, créez une table intermédiaire de ItemID / TagID et mettez-y le " Perfect Index ".

Timothy Khouri
la source