¿Cuál es la forma más eficiente de almacenar etiquetas en una base de datos?

138

Estoy implementando un sistema de etiquetado en mi sitio web similar a uno que usa stackoverflow, mi pregunta es: ¿cuál es la forma más efectiva de almacenar etiquetas para que puedan ser buscadas y filtradas?

Mi idea es esta:

Table: Items
Columns: Item_ID, Title, Content

Table: Tags
Columns: Title, Item_ID

¿Esto es demasiado lento? ¿Hay una mejor manera?

Logan Serman
fuente
2
Preguntado previamente: stackoverflow.com/questions/20856/…
DrBloodmoney
1
A partir de 2016, use Solr o Elasticsearch
Charles L.

Respuestas:

189

Un artículo tendrá muchas etiquetas. Y una etiqueta pertenecerá a muchos artículos. Esto implica para mí que posiblemente necesitará una tabla intermedia para superar el obstáculo de muchos a muchos.

Algo como:

Tabla:
Columnas de elementos : Item_ID, Item_Title, Content

Tabla:
Columnas de etiquetas : Tag_ID, Tag_Title

Tabla:
Columnas Items_Tags: Item_ID, Tag_ID

Puede ser que su aplicación web sea increíblemente popular y necesite una desnormalización en el camino, pero no tiene sentido enturbiar las aguas demasiado pronto.

Simon Scarfe
fuente
si hay algo como tagGroup, cómo manejarlo, por ejemplo, las etiquetas se agrupan en categorías, por ejemplo: Lenguajes de programación: c #, vb, pearl. Sistema operativo: Windows7, DOS, Linux, etc.
Trueno
44
@Thunder: suponiendo que una etiqueta solo pueda pertenecer a una categoría, crearía una tabla TagCategory compuesta por category_id y category_name. A partir de ahí, agregaría un campo category_id a la tabla Etiquetas y realizaría una unión sobre eso.
Simon Scarfe
114

Debería leer las publicaciones de blog de Philipp Keller sobre etiquetar esquemas de bases de datos. Intenta algunos e informa sus resultados, tanto en términos de facilidad para construir consultas comunes como en términos de rendimiento . El número de etiquetas, el número de artículos etiquetados y el número de etiquetas por artículo fueron factores. Las publicaciones son de 2005; No tengo conocimiento de ninguna actualización desde entonces.

Rob Kennedy
fuente
19
Creo que esta es la mejor respuesta. Se basa en pruebas e investigaciones reales en lugar de suposiciones como la mayoría de las otras respuestas.
Cristian Vrabie
44
Los enlaces en la respuesta no parecen funcionar. Encontré una copia en vtidter.blogspot.be/2014/02/database-schema-for-tags.html
Christophe Herreman el
8

En realidad, creo que la normalización de la tabla de etiquetas podría ser una mejor manera de avanzar, dependiendo de la escala.

De esta manera, la tabla de etiquetas simplemente tiene tagid, itemid, tagname.

Obtendrá nombres de etiquetas duplicados, pero hace que agregar / quitar / editar etiquetas para elementos específicos sea MUCHO más simple. No tiene que crear una nueva etiqueta, eliminar la asignación de la anterior y volver a asignar una nueva, solo edite el nombre de la etiqueta.

Para mostrar una lista de etiquetas, simplemente use DISTINCT o GROUP BY y, por supuesto, también puede contar cuántas veces se usa una etiqueta fácilmente.

Neil Barnwell
fuente
4

Si no le importa usar un poco de material no estándar, Postgres versión 9.4 y superior tiene la opción de almacenar un registro de tipo de matriz de texto JSON.

Tu esquema sería:

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

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

Para obtener más información, consulte esta excelente publicación de Josh Berkus: http://www.databasesoup.com/2015/01/tag-all-things.html

Hay más opciones diferentes comparadas a fondo para el rendimiento y la sugerida anteriormente es la mejor en general.

Dmitry Shvedov
fuente
2

Sugeriría usar la tercera tabla intermedia para almacenar etiquetas <=> asociaciones de elementos, ya que tenemos relaciones de muchos a muchos entre etiquetas y elementos, es decir, un elemento puede asociarse con múltiples etiquetas y una etiqueta puede asociarse con múltiples elementos. HTH, válvula.

Valentin Vasilyev
fuente
1

Realmente no se puede hablar de lentitud en función de los datos que proporcionó en una pregunta. Y no creo que deba preocuparse demasiado por el rendimiento en esta etapa de desarrollo. Se llama optimización prematura .

Sin embargo, sugiero que incluya la columna Tag_ID en la tabla Etiquetas. Por lo general, es una buena práctica que cada tabla tenga una columna de ID.

Rockcoder
fuente
1

Si el espacio va a ser un problema, tenga una tercera tabla de etiquetas (Tag_Id, Título) para almacenar el texto de la etiqueta y luego cambie su tabla de etiquetas para que sea (Tag_Id, Item_Id). Esos dos valores también deberían proporcionar una clave primaria compuesta única.

Adam Pope
fuente
0

Los elementos deben tener un campo "ID", y las etiquetas deben tener un campo "ID" (Clave primaria, agrupada).

Luego haga una tabla intermedia de ItemID / TagID y coloque el " Índice Perfecto " allí.

Timothy Khouri
fuente