Aanbevolen SQL database ontwerp voor tags of tagging

Ik heb gehoord van een paar manieren om te implementeren tagging; met behulp van een mapping tabel tussen TagID en ItemID (zinvol voor mij, maar doet het in de schaal?), het toevoegen van een vast aantal mogelijke TagID kolommen ItemID (lijkt me een slecht idee), het Houden van tags in een tekst kolom die door komma ‘ s gescheiden (klinkt gek, maar kon het werk). Ik heb zelfs gehoord van iemand adviseren een sparse matrix, maar hoe doen de namen van tags groeien sierlijk?

Ben ik het missen van een best practice voor tags?

InformationsquelleAutor dlamblin | 2008-08-21

 

6 Replies
  1. 384

    Drie tabellen: één voor het opslaan van alle items een voor alle tags, en één voor de relatie tussen de twee), goed geïndexeerd worden, met vreemde sleutels set draaien op een goede database, moet goed werken en de schaal goed.

    Table: Item
    Columns: ItemID, Title, Content
    
    Table: Tag
    Columns: TagID, Title
    
    Table: ItemTag
    Columns: ItemID, TagID
    • Dit is bekend als de “Toxi” oplossing kunt u aanvullende informatie vinden over het hier : pui.ch/phred/archives/2005/04/tags-database-schemas.html
    • Één ding niet hier getoond wordt hiërarchische “tags” of categorieën in de Tag tabel. Dit is vaak nodig op sites die categorieën en subcategorieën, maar de flexibiliteit van tagging. Bijvoorbeeld, recept sites, auto-onderdelen sites, business directories, etc. Deze types van gegevens meestal niet passen in slechts één categorie dus tagging is het antwoord, maar je moet iets als het Geneste Model of het Adjacency List Model in uw Tag tabel.
    • Ik agrree met HK1 is het mogelijk met bovenstaande structuur + Tabel : TagGroup Kolommen : TagGropuId, Tabel Titel: Tag Kolommen: TagID, Titel , TagGroupId
    • als ik wil toevoegen css kolom aan tafel,ik zal het toevoegen van css kolom in tag tafel?
    • Ik dacht dat de tabel ItemTag moet een Kolom ItemTagID. Ben ik verkeerd? mis ik iets?
    • Ik denk dat de table-Tag moet alleen de titel PK, met een aparte ID als primaire sleutel vooral een automatische verhoging zou resulteren in de table-Tag krijgen gevuld met dubbele waarden bij het inbrengen/bijwerken (in een ManyToMany relatie).
    • link opnieuw gebroken, de nieuwe link is howto.philippkeller.com/2005/04/24/Tags-Database-schemas

  2. 76

    Normaal gesproken zou ik eens met Yaakov Ellis, maar in dit speciale geval is er een andere oplossing:

    Gebruik maken van twee tabellen:

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

    Dit heeft een aantal grote voordelen:

    Eerste het maakt de ontwikkeling veel eenvoudiger: in de drie-tabel oplossing voor insert en update van item je moet zoeken Tag tabel om te zien of er al items. Dan heb je bij hen aan te sluiten met nieuwe. Dit is geen triviale taak.

    Dan maakt query ‘ s eenvoudiger (en misschien wel sneller). Er zijn drie grote database query ‘ s die u zal doen: Output alle Tags voor een Item, het trekken van een Tag-Cloud en selecteer alle items voor een Tag Titel.

    Alle Tags voor één Item:

    3-Tabel:

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

    2-Tabel:

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

    Tag-Cloud:

    3-Tabel:

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

    2-Tabel:

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

    Items voor één Tag:

    3-Tabel:

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

    2-Tabel:

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

    Maar er zijn enkele nadelen: Er kan nemen meer ruimte in de database (die kunnen leiden tot meer schijf operaties die is langzamer) en het is niet genormaliseerd, wat kan leiden tot inconsistenties.

    De grootte argument is niet zo sterk omdat de aard van tags is dat ze normaal gesproken vrij klein, zodat de grootte stijging is niet groot. Men zou kunnen stellen dat de query voor de titel tag is veel sneller in een kleine tabel waarin elke tag wordt slechts eenmaal en dit is zeker waar. Maar in verband met de besparing voor het niet hebben om mee te doen en het feit dat u kunt bouwen aan een goede index op hen gemakkelijk kunnen dit compenseren. Dit is natuurlijk sterk afhankelijk van de grootte van de database die u gebruikt.

    De inconsistentie argument is een beetje discutabel ook. Tags zijn vrije tekstvelden en er is geen verwachte transactie als ‘de naam van alle tags “foo” op “bar”‘.

    Dus tldr: ik zou gaan voor de twee-tabel oplossing. (In feite ben ik gaan. Ik vond dit artikel om te zien of er geldige argumenten tegen.)

    • Doet “Index: ItemId, Titel” betekent een index voor elk of een index die beide?
    • Normaal gesproken twee indexen. Kan afhankelijk van de database die u gebruikt, hoewel.
    • In de tag tabel is ItemId en Tag een samengestelde sleutel? of heb je een PK zo goed?
    • Ik denk dat dit afhankelijk is van de soort van raamwerk u / hoe u gebruikt voor het schrijven van code. Soms is het makkelijker om een primaire sleutel is en soms is het niet. In mijn geval heb ik een PK omdat ik graag nog iets willen VERWIJDEREN?id=5 dan VERWIJDEREN?idemid=3&tag=Foo in de web client. Uit een data-consistentie standpunt aan de andere kant zou ik niet gebruik maken van een extra PK. En voor onderwijsdoeleinden ik zou het niet aanraden 🙂
    • Over Scheintod de twee tabel oplossing, het zou moeten werken, maar er zijn een paar beperkingen. 1. Als je tags hebben alle bijbehorende gegevens (bijvoorbeeld, als je een tag is een beschrijving of een aantal andere gegevens) vermenigvuldigen gelabelde objecten niet kon hebben hun metadata bewerkt consequent zonder veel werk te doen om ze te houden in sync. 2. Er is wat extra opslagruimte die betrokken zijn bij lange titels en tags worden gebruikt, vele malen. In een 2 tabel oplossing, zou de titel opnieuw worden ingevoerd vele malen. Misschien dat sommige DBs zou het optimaliseren van de gegevens als onderdeel van hun opslag/indexing, maar ik ben er niet zeker van. In mijn geval,
    • Hi, je zegt: “het nemen van in verband met de besparing voor het niet hebben om mee te doen en het feit dat u kunt bouwen aan een goede index” – de ‘kleine’ tabel zal ook worden geïndexeerd, de index omvang zal worden aanzienlijk minder. join op FK die int moet veel sneller dan het opvragen van een grote index van nvarchar(n). Met dat gezegd, ik vind dit idee en het zal waarschijnlijk een afleiding van het om mee te doen veel verschillende typen (tabellen) met common-tags.
    • HI h.alex. Het punt is, dat je minder te doen joins die kan blijken sneller te zijn dan het hebben van hen samen met een int FK. Maar gezien het feit dat normaal gesproken Tag tabellen zijn meestal klein is het verschil in snelheid (in welke richting dan ook) kan niet merkbaar is op alle. Hier is een ander artikel dat vergelijkt ongeveer de beide technieken: dba.stackexchange.com/questions/15897/…
    • corrigeer me als ik verkeerd ben, maar wanneer ik een item verwijderen zal er een null-waarde in de rij, en als ik het verwijder alle items zal er worden een heleboel herhalen instellen van alle rijen met lege waarden voor itemid?
    • Ik weet het niet zeker, waar je het over hebt (maar het is nog vroeg in de ochtend). Als u een item verwijdert u moet verwijderen van de labels met het. Afhankelijk van de werkelijke database implementatie (foreign key constraint) de database niet in de steek laten verwijderen totdat u hebt verwijderd van de tags.
    • in mijn applicatie heb ik een aantal tags die vooraf geladen kan ik niet durven verwijderen van de tags, maar ik kan cascade neutraliseren, waardoor een veel dubbele nutteloos rijen, ik vind het idee van het afschaffen van de mapping tabel hoewel
    • waar is de originele tag-lijst opgeslagen ? web pagina ?
    • dit kun je niet maken “ongebruikte” tags dus een “tag toevoegen” – functie moet worden uitgevoerd op een Item. Aan de andere methode, de “add tag” – functie kan zelfstandig worden uitgevoerd
    • Hallo ik vraag me af of u nog steeds van mening 2-tabel oplossing is beter 3-tabel oplossing na al die jaren ?
    • Ik geloof nog steeds dat hangt af van wat je aan toe bent 🙂 ik heb uitgevoerd is het op beide manieren in de verschillende projecten. In mijn voorlaatste ik eindigde met een 3 tabel oplossing, omdat ik nodig een “tag-type” (of een andere meta-informatie op de tag) en kon hergebruik van code van een nauwe neef van tags: parameters. Maar in hetzelfde project waar ik precies gebruikt deze methode voor een nog nader neef: vlaggen (bv. ‘verkocht’, ‘nieuw’, ‘warm’)

  3. 37

    Als u gebruik maakt van een database dat ondersteunt kaart-te verminderen, zoals couchdb, het opslaan van tags in een tekst-veld of veld lijst is inderdaad de beste manier. Voorbeeld:

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

    Het uitvoeren van deze groep=true groep zal de resultaten door tag-naam, en zelfs een telling van het aantal keer dat de tag is opgetreden. Het is zeer vergelijkbaar met het tellen van de aanwezigheid van een woord in de tekst.

    • +1 Mooi om te zien dat sommige NoSQL implementaties ook.
    • De link werkt niet. Als je kon, please update van dit antwoord.
    • Ok ik heb het vervangen van de koppeling met een te archive.org
  4. 12

    Gebruik een enkele-opgemaakte tekst in kolom[1] voor het opslaan van de tags en het gebruik van een staat om full-text search-engine te indexeren. Anders zal je in de schalen voor problemen bij het implementeren van boolean query ‘ s.

    Als u details over de tags die je hebt, je kunt houden in een incrementeel onderhouden tafel of het uitvoeren van een batch job uitpakken van de informatie.

    [1] Sommige RDBMS zelfs een native array type die wellicht nog beter geschikt voor de opslag van door niet nodig een parseren stap, maar kan problemen veroorzaken met de volledige tekst zoeken.

    • Bent u zich bewust van een full-text search-engine die niet vinden variaties op een woord? Bijvoorbeeld, zoeken naar boeken geeft boeken? Ook, wat doe je met tags zoals “c++”? SQL Server, bijvoorbeeld, zou de strook van het plus teken in de index. Bedankt.
    • Probeer Sphinx – sphinxsearch.com
    • Deze 3-delige tutorial misschien nuttig zijn voor degenen die deze route te gaan (full text search). Het gebruik van PostgreSQL native faciliteiten: shisaa.jp/postset/postgresql-full-text-search-part-1.html
    • is dit beter dan het gekozen antwoord in termen van prestaties ?
    • hoe zit het met het opslaan in het gebruik van varchar 255, komma afgezet tags en toevoegen kfull tekst index op ?
  5. 9

    Ik heb altijd gehouden van de tags in een aparte tabel en had toen een mapping tabel. Natuurlijk heb ik nog nooit iets gedaan op een zeer grote schaal, hetzij.

    Het hebben van een “tags” tabel en een kaart tafel maakt het vrij makkelijk om het genereren van tag clouds & zo, want je kunt gemakkelijk samen SQL om een lijst van tags met graven van hoe vaak een tag wordt gebruikt.

    • Dit is nog meer het makkelijk als je geen gebruik maken van een mapping tabel 🙂
  6. 0

    Ik zou suggereren volgende ontwerp :
    Tabel Item:
    Itemid, taglist1, taglist2

    deze worden snel en eenvoudig opslaan en ophalen van de gegevens op item-niveau.

    Parallel bouwen van een andere tabel:
    Tags
    tag
    maak geen unieke id tag en als je opraken van de ruimte in de 2e kolom bevat, laten we zeggen 100 items maken van een andere rij.

    Nu tijdens het zoeken naar items voor een tag zal worden super snel.

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *