Autor Zpráva
Mesiah
Profil
Ahoj,

prosím Vás, jaká je best-practise pro vytvoření tabulky, která je použita pro více zdrojů?
Krásný příklad jsou komentáře - mám tabulku Comment (id, text, created, user_id) a teď si představme, že chci stejnou tabulku s komentáři použít pro články, pro fotky, pro celá alba.
V podstatě je, jak už to v relačních databázích bývá, několik možností:
1) můžu mít tolik vazebních tabulek, kolik potřebuji spojení, v tomto případě 3 (Article_Comment, Photo_Comment, Album_comment)
2) mít odkaz na zdroje v tabulce Comment (article_id, photo_id, album_id přímo v tbl Comment) ale pokud se nepletu, tak tohle minimálně porušuje normální pravidla
3) mít jednu vazební tabulku Comment_Link (comment_id, article_id, photo_id, album_id) asi lepší než předchozí, ale pořád nešikovné a pořád porušuje normální pravidla

Takhle na pohled se mi nejvíce líbí 1. možnost, ale psaní dotazů bude celkem peklo - třeba vypsat komentáře v rozsahu datumů a k nim k čemu se vážou - to už pak první řešení není zas tak hezké...
Máte nějaké doporučení?
Jen doplním, že nad db je/bude ORM.
tiso
Profil
4) mať v tabuľke komentárov stĺpce entity_type a entity_id
5) miesto jednej tabuľky s komentármi ich mať viac
juriad
Profil
6) mít tabulku
commentable (id auto_increment, type varchar)
od které budou odvozené další tabulky
article(commentable_id FK, ...)
photo(commentable_id FK, ...)
...
a komentář bude mít cizí klíč na commentable.id

Uvažuj nad tabulkou commentable jako nad globální sekvencí id-ček.
Volitelně můžou mít tabulky article, photo ještě svá vlastní id-čka, a naopak atribut type v commentable nemusí být potřeba.


Tyto a další úvahy můžeš najít v prezentaci http://www.slideshare.net/billkarwin/sql-antipatterns-strike-back od strany 32.
Mesiah
Profil
juriad: díky moc za odkaz na slide, zatím jsem je jen rychle prolítl, ale libí se mi!
Jinak pokud jsem to pochopil správně - myslím ten alternativní nápad s tím, že tabulky article a photo budou mít vlastní ID, tak tabulka Commentable by měla jednak sdílený index (Id) a pak klasický index nad bigint, kam by se uchovávali Id z tabulek Article a Photo, ale fyzicky by tam nebyl FK?
juriad
Profil
Zkusím to namodelovat.
Ta základní varianta s jediným klíčem: http://sqlfiddle.com/#!2/3c977/1
Pokud chceš mít oddělený prostor id-ček pro články a fotky: http://sqlfiddle.com/#!2/c1bf0/3
Mesiah
Profil
juriad: nádhera. Víc se mi líbí ten první způsob, ale zajímalo by mě jestli je rozdíl ve výkonu databáze... Škoda, že jsem nebyl na té přednášce... :)
juriad
Profil
Insert se vykonává jako dva po sobě jdoucí inserty; počet insertů se tedy zdvojnásobí + nějaká režie na trigger. Předpokládám, že to problém nebude. Vzhledem k tomu, že schéma vypadá na nějaké sociální médium, budou uživatelé mnohem časti prohlížet (select) než vkládat (insert) obsah.

Samotný select je jednoduchý, jeden join. V podstatě se neliší od jiných navrhovaných variant, jen dává id-íčku jiný význam (není to přímo článek, nebo fotka, ale je to jakýkoli komentovatelný objekt).

Dotaz na nejnovější komentáře bez ohledu na typ přičemž tě zajímají i podrobnosti o komentovaném objektu bude ve všech případech složitý (vždy bude potreba UNION).
V navrhovaném schématu bys mohl třeba jméno fotky nebo název článku přesunout do tabulky commentable jako jediný atribut (name). Tím by sis mohl zjednodušit výše uvedený select.

Cizí klíče můžeš a nemusíš používat, v MyISAM jsou tam stejně jen na okrasu. Vynucování integrity pomocí cizích klíčů může snížit výkon.
V případě výkonových problémů je pak otázkou, zda je volba MySQL vhodná pro takovou aplikaci. V takovém případě bys nejspíš narážel na problémy i v jiných situacích.

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0