Qual é a maneira mais eficiente de armazenar tags em um banco de dados?

138

Estou implementando um sistema de marcação no meu site semelhante ao que um stackoverflow usa, minha pergunta é: qual é a maneira mais eficaz de armazenar tags para que possam ser pesquisadas e filtradas?

Minha ideia é esta:

Table: Items
Columns: Item_ID, Title, Content

Table: Tags
Columns: Title, Item_ID

Isso é muito lento? Existe uma maneira melhor?

Logan Serman
fonte
2
Perguntado anteriormente: stackoverflow.com/questions/20856/…
DrBloodmoney 2/08/08
1
A partir de 2016, use Solr ou Elasticsearch
Charles L.

Respostas:

189

Um item terá muitas tags. E uma tag pertencerá a muitos itens. Isso implica para mim que você possivelmente precisará de uma tabela intermediária para superar o obstáculo de muitos para muitos.

Algo como:

Tabela:
Colunas de itens : Item_ID, Item_Title, Content

Tabela: Tags
Colunas: Tag_ID, Tag_Title

Tabela: Items_Tags
Colunas: Item_ID, Tag_ID

Pode ser que seu aplicativo da Web seja incrivelmente popular e precise desnormalizar mais adiante, mas é inútil enlamear as águas muito cedo.

Simon Scarfe
fonte
se houver algo como tagGroup, como lidar com isso, por exemplo, as tags são agrupadas em categorias, por exemplo: Linguagens de programação: c #, vb, pearl. OS: windows7, dos, linux, etc #
Thunder
4
@ Thunder: supondo que uma tag só possa pertencer a uma categoria, eu criaria uma tabela TagCategory consistindo em category_id e category_name. A partir daí, eu acrescentaria um campo category_id à tabela Tags e realizaria uma junção.
Simon Scarfe
114

Você deve ler as postagens do blog de Philipp Keller sobre a marcação de esquemas de banco de dados. Ele tenta alguns e relata seus resultados, tanto em termos de facilidade na construção de consultas comuns quanto em termos de desempenho . Número de tags, número de itens marcados e número de tags por item foram todos fatores. Os posts são de 2005; Não tenho conhecimento de nenhuma atualização desde então.

Rob Kennedy
fonte
19
Eu acho que essa é a melhor resposta. Baseia-se em testes e pesquisas reais, em vez de suposições, como a maioria das outras respostas.
Cristian Vrabie
4
Os links na resposta não parecem funcionar. Encontrado uma cópia em vtidter.blogspot.be/2014/02/database-schema-for-tags.html
Christophe Herreman
8

Na verdade, acredito que des-normalizar a tabela de tags pode ser um caminho melhor a seguir, dependendo da escala.

Dessa forma, a tabela de tags simplesmente possui tagid, itemid, tagname.

Você receberá nomes de tag duplicados, mas isso facilita a adição / remoção / edição de tags de itens específicos. Você não precisa criar uma nova tag, remover a alocação da antiga e realocar uma nova, basta editar o nome da tag.

Para exibir uma lista de tags, basta usar DISTINCT ou GROUP BY e, é claro, você pode contar quantas vezes uma tag também é usada com facilidade.

Neil Barnwell
fonte
4

Se você não se importa em usar um pouco de coisas não padronizadas, o Postgres versão 9.4 e posterior tem a opção de armazenar um registro do tipo de matriz de texto JSON.

Seu esquema seria:

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

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

Para obter mais informações, consulte este excelente post de Josh Berkus: http://www.databasesoup.com/2015/01/tag-all-things.html

Existem várias opções comparadas minuciosamente para desempenho e a sugerida acima é a melhor em geral.

Dmitry Shvedov
fonte
2

Eu sugiro usar a terceira tabela intermediária para armazenar associações de itens de tags <=>, uma vez que temos relações muitos-para-muitos entre tags e itens, ou seja, um item pode ser associado a várias tags e uma tag pode ser associada a vários itens. HTH, válvula.

Valentin Vasilyev
fonte
1

Você não pode realmente falar sobre lentidão com base nos dados que você forneceu em uma pergunta. E não acho que você deva se preocupar muito com o desempenho nesse estágio de desenvolvimento. Isso se chama otimização prematura .

No entanto, sugiro que você inclua a coluna Tag_ID na tabela Tags. Geralmente, é uma boa prática que todas as tabelas tenham uma coluna de ID.

Rockcoder
fonte
1

Se o espaço for um problema, tenha uma terceira tabela de Tags (Tag_Id, Title) para armazenar o texto da tag e altere a tabela de Tags para (Tag_Id, Item_Id). Esses dois valores também devem fornecer uma chave primária composta exclusiva.

Adam Pope
fonte
0

Os itens devem ter um campo "ID" e os Tags devem ter um campo "ID" (Chave Primária, Clusterizada).

Em seguida, faça uma tabela intermediária de ItemID / TagID e coloque o " Índice Perfeito " lá.

Timothy Khouri
fonte