Jaki jest najbardziej efektywny sposób przechowywania tagów w bazie danych?

138

Wdrażam system tagowania w mojej witrynie podobny do tego, którego używa stackoverflow, moje pytanie brzmi - jaki jest najskuteczniejszy sposób przechowywania tagów, aby można je było wyszukiwać i filtrować?

Mój pomysł jest taki:

Table: Items
Columns: Item_ID, Title, Content

Table: Tags
Columns: Title, Item_ID

Czy to za wolno? Czy jest lepszy sposób?

Logan Serman
źródło
2
Wcześniej zadane
DrBloodmoney
1
Od 2016 r. Używaj Solr lub Elasticsearch
Charles L.

Odpowiedzi:

189

Jedna pozycja będzie miała wiele tagów. Jeden tag będzie należał do wielu przedmiotów. To sugeruje mi, że prawdopodobnie będziesz potrzebować stołu pośredniego, aby pokonać przeszkodę wiele do wielu.

Coś jak:

Tabela:
Kolumny pozycji : Item_ID, Item_Title, Treść

Tabela: Tagi
Kolumny: Tag_ID, Tag_Title

Tabela: Items_Tags
Kolumny: Item_ID, Tag_ID

Może się zdarzyć, że Twoja aplikacja internetowa jest szalenie popularna i wymaga denormalizacji w przyszłości, ale zbyt wczesne mulenie wód jest bezcelowe.

Simon Scarfe
źródło
jeśli istnieje coś takiego jak tagGroup, jak sobie z tym poradzić, np. tagi są pogrupowane w kategorie, np .: Języki programowania: c #, vb, pearl. System operacyjny: windows7, dos, linux itp.
Thunder
4
@Thunder: zakładając, że jeden tag może należeć tylko do jednej kategorii, utworzyłbym tabelę TagCategory składającą się z category_id i category_name. Stamtąd dołączyłbym pole category_id do tabeli Tags i wykonałem na nim łączenie.
Simon Scarfe
114

Powinieneś przeczytać posty na blogu Philippa Kellera dotyczące tagowania schematów baz danych. Próbuje kilku i raportuje swoje wyniki, zarówno pod względem łatwości konstruowania typowych zapytań , jak i pod względem wydajności . Liczba tagów, liczba oznakowanych elementów i liczba tagów na element były czynnikami. Stanowiska pochodzą z 2005 roku; Od tego czasu nie wiem o żadnych aktualizacjach.

Rob Kennedy
źródło
19
Myślę, że to najlepsza odpowiedź. Opiera się na rzeczywistych testach i badaniach, a nie na przypuszczeniach, jak większość innych odpowiedzi.
Cristian Vrabie
4
Wydaje się, że linki w odpowiedzi nie działają. Kopię znaleziono pod adresem vtidter.blogspot.be/2014/02/database-schema-for-tags.html
Christophe Herreman
8

Właściwie uważam, że cofnięcie normalizacji tabeli tagów może być lepszym rozwiązaniem, w zależności od skali.

W ten sposób tablica tagów zawiera po prostu tagid, itemid, tagname.

Otrzymasz zduplikowane zmienne, ale to sprawia, że ​​dodawanie / usuwanie / edytowanie tagów dla określonych pozycji jest DUŻO prostsze. Nie musisz tworzyć nowego znacznika, usuwać przypisania starego i ponownie przydzielać nowego, po prostu edytujesz zmienną.

Aby wyświetlić listę tagów, po prostu użyj DISTINCT lub GROUP BY i oczywiście możesz też policzyć, ile razy tag jest używany z łatwością.

Neil Barnwell
źródło
4

Jeśli nie masz nic przeciwko użyciu nieco niestandardowych rzeczy, Postgres w wersji 9.4 i nowszych ma opcję przechowywania rekordu typu tablica tekstowa JSON.

Twój schemat wyglądałby tak:

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

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

Aby uzyskać więcej informacji, zobacz ten doskonały post Josha Berkusa: http://www.databasesoup.com/2015/01/tag-all-things.html

Istnieje więcej różnych opcji dokładnie porównanych pod kątem wydajności, a ta sugerowana powyżej jest ogólnie najlepsza.

Dmitry Shvedov
źródło
2

Sugerowałbym użycie trzeciej tabeli pośredniczącej do przechowywania tagów <=> skojarzeń elementów, ponieważ mamy relacje „wiele do wielu” między tagami i elementami, tj. Jeden element może być powiązany z wieloma tagami, a jeden tag może być powiązany z wieloma elementami. HTH, zawór.

Walentyna Wasiljewa
źródło
1

Nie możesz naprawdę mówić o powolności na podstawie danych podanych w pytaniu. I nie sądzę, żebyś na tym etapie rozwoju martwił się zbytnio o wydajność. Nazywa się to przedwczesną optymalizacją .

Sugerowałbym jednak uwzględnienie kolumny Tag_ID w tabeli Tagi. Zwykle dobrą praktyką jest, aby każda tabela miała kolumnę ID.

Rockcoder
źródło
1

Jeśli problemem będzie miejsce, miej trzecią tabelę Tagi (Tag_Id, Tytuł) do przechowywania tekstu dla znacznika, a następnie zmień tabelę Tagi na (Tag_Id, Item_Id). Te dwie wartości również powinny zapewniać unikalny złożony klucz podstawowy.

Adam Pope
źródło
0

Elementy powinny mieć pole „ID”, a tagi powinny mieć pole „ID” (klucz podstawowy, klastrowany).

Następnie utwórz pośrednią tabelę ItemID / TagID i umieść tam „ Perfect Index ”.

Timothy Khouri
źródło