Zalecany projekt bazy danych SQL dla tagów lub tagów [zamknięty]

Słyszałem o kilku sposobach implementacji tagowania; używanie tabeli mapowania pomiędzy TagID i ItemID (ma sens, ale czy jest skalowany?), dodanie stałej liczby możliwych kolumn TagID do ItemID( wydaje się złym pomysłem), utrzymanie tagów w kolumnie tekstowej oddzielonej przecinkami (brzmi szalenie, ale może działać). Słyszałem nawet, że ktoś poleca rzadką matrycę, ale w jaki sposób nazwy tagów rosną wdzięcznie?

Czy brakuje mi najlepszych praktyk dla tagów?

Author: Dan Dascalescu, 2008-08-21

6 answers

Trzy tabele (jedna do przechowywania wszystkich elementów, jedna do wszystkich znaczników i jedna do relacji między nimi), odpowiednio zindeksowane, z ustawionymi kluczami obcymi działającymi na odpowiedniej bazie danych, powinny działać dobrze i odpowiednio skalować.

Table: Item
Columns: ItemID, Title, Content

Table: Tag
Columns: TagID, Title

Table: ItemTag
Columns: ItemID, TagID
 365
Author: Yaakov Ellis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-21 19:22:44

Normalnie zgodziłbym się z Yaakovem Ellisem, ale w tym szczególnym przypadku jest inne realne rozwiązanie:

Użyj dwóch tabel:

Table: Item
Columns: ItemID, Title, Content
Indexes: ItemID

Table: Tag
Columns: ItemID, Title
Indexes: ItemId, Title

To ma kilka głównych zalet:

Po pierwsze sprawia, że rozwój jest znacznie prostszy: w trójstopniowym rozwiązaniu insert I update item musisz wyszukać tabelę Tag, aby sprawdzić, czy są już wpisy. Następnie musisz dołączyć do nich nowe. To nie jest trywialne zadanie.

Potem sprawia, że zapytania są prostsze (i być może szybciej). Istnieją trzy główne zapytania bazy danych, które wykonasz: Wyjście wszystkich {[9] } dla jednego Item, narysowanie chmury znaczników i zaznaczenie wszystkich elementów dla jednego tytułu znacznika.

Wszystkie tagi dla jednego elementu:

3-Tabela:

SELECT Tag.Title 
  FROM Tag 
  JOIN ItemTag ON Tag.TagID = ItemTag.TagID
 WHERE ItemTag.ItemID = :id

2-Tabela:

SELECT Tag.Title
FROM Tag
WHERE Tag.ItemID = :id

Tag-Cloud:

3-Tabela:

SELECT Tag.Title, count(*)
  FROM Tag
  JOIN ItemTag ON Tag.TagID = ItemTag.TagID
 GROUP BY Tag.Title

2-Tabela:

SELECT Tag.Title, count(*)
  FROM Tag
 GROUP BY Tag.Title

Artykułów dla jednego tagu:

3-Tabela:

SELECT Item.*
  FROM Item
  JOIN ItemTag ON Item.ItemID = ItemTag.ItemID
  JOIN Tag ON ItemTag.TagID = Tag.TagID
 WHERE Tag.Title = :title

2-Tabela:

SELECT Item.*
  FROM Item
  JOIN Tag ON Item.ItemID = Tag.ItemID
 WHERE Tag.Title = :title

Ale są pewne wady: może to zająć więcej miejsca w bazie danych (co może prowadzić do większej ilości operacji na dysku, która jest wolniejsza) i nie jest znormalizowana, co może prowadzić do niespójności.

Argument size nie jest tak silny, ponieważ sama natura tagów polega na tym, że zwykle są one dość małe, więc wzrost rozmiaru nie jest duży. Można argumentować, że Zapytanie o tytuł tagu jest znacznie szybsze w małej tabeli, która zawiera każdy tag tylko raz i to z pewnością jest prawdą. Ale biorąc w zwróć uwagę na oszczędności za to, że nie musisz dołączać, a fakt, że możesz zbudować na nich dobry indeks, może łatwo to zrekompensować. To oczywiście zależy w dużej mierze od wielkości bazy danych, której używasz.

Argument niespójności jest również trochę dyskusyjny. Tagi są wolnymi polami tekstowymi i nie ma oczekiwanej operacji takiej jak 'Zmień nazwę wszystkich tagów" foo " na "bar"'.

Więc tldr: wybrałbym rozwiązanie dwustawne. (W rzeczywistości zamierzam. Znalazłem ten artykuł, aby sprawdzić, czy są ważne argumenty przeciw.)

 66
Author: Scheintod,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-04 16:49:34

Jeśli używasz bazy danych obsługującej map-reduce, jak couchdb, przechowywanie znaczników w polu tekstowym lub polu listy jest rzeczywiście najlepszym sposobem. Przykład:

tagcloud: {
  map: function(doc){ 
    for(tag in doc.tags){ 
      emit(doc.tags[tag],1) 
    }
  }
  reduce: function(keys,values){
    return values.length
  }
}

Uruchomienie tego z group = true spowoduje pogrupowanie wyników według nazwy znacznika, a nawet zwróci liczbę razy, ile ten znacznik został napotkany. Jest bardzo podobny do zliczania wystąpień słowa w tekście .

 37
Author: Nick Retallack,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-20 04:47:45

Użyj jednej sformatowanej kolumny tekstowej[1] do przechowywania znaczników i użyj zdolnej Wyszukiwarki pełnotekstowej do indeksowania tego. W przeciwnym razie napotkasz problemy ze skalowaniem podczas próby implementacji zapytań logicznych.

Jeśli potrzebujesz szczegółów na temat posiadanych tagów, możesz albo śledzić je w tabeli utrzymywanej przyrostowo, albo uruchomić zadanie wsadowe, aby wyodrębnić informacje.

[1] Niektóre RDBMS zapewniają nawet natywny typ tablicy, który może być nawet lepiej dostosowany do pamięci masowej, ponieważ nie wymaga krok parsowania, ale może powodować problemy z wyszukiwaniem pełnego tekstu.

 11
Author: David Schmitt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-07 11:47:34

Zawsze trzymałem znaczniki w osobnej tabeli, a potem miałem tabelę mapowania. Oczywiście nigdy nie robiłem niczego na naprawdę dużą skalę.

Posiadanie tabeli "tags" i tabeli map sprawia, że generowanie chmur znaczników jest dość trywialne, ponieważ można łatwo połączyć SQL, aby uzyskać listę tagów z licznikami, jak często każdy tag jest używany.

 8
Author: Mark Biek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-21 19:23:32

Proponuję następujący projekt : Tabela Pozycji: Itemid, taglist1, taglist2
będzie to szybkie i łatwe zapisywanie i pobieranie danych na poziomie pozycji.

Równolegle buduj kolejną tabelę: Tagi znacznik nie rób znacznika unikalnym identyfikatorem i jeśli zabraknie miejsca w 2 kolumnie, która zawiera powiedzmy 100 elementów, utwórz kolejny wiersz.

Teraz podczas wyszukiwania elementów dla tagu będzie super szybko.

 0
Author: user236575,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-28 09:51:15