mcdronkz schreef op zaterdag 27 augustus 2016 @ 22:29:
Ik ben bezig met het modelleren van de databasestructuur voor een pricewatch-achtig product, maar dan voor de metaalbranche. Deze database bevat vele duizenden producten, ingedeeld in honderden productsoorten. Deze productsoorten hebben op hun beurt weer uiteenlopende attributen (producteigenschappen).
Toevallig weet ik wel iets van de Pricewatch
Wij gebruiken ook 'gewoon' een EAV-model. Productsoorten is daarbij losgetrokken en heet bij ons categorie. Die hebben een hierarchisch model (effectief een tree), overigens gewoon met een parentId-veld in de category-tabel.
Wat is het meest geschikte ontwerp voor een dergelijke database?
Ik zou er op voorhand rekening mee houden dat er niet één geschikt model is. Voor opslag, bewerken en tonen van specifieke productpagina's zal een RDBMS best goed werken (bij ons iig wel). Voor het doorzoeken, zeker zodra dat gefacetteerd moet (zie specificatie-filters in de PW) gaat een SQL-database niet goed werken.
Een ondertussen redelijk klassieke oplossing is om de data primair in je RDBMS op te slaan. Voor het efficient doorzoeken wordt het dan vaak gedenormalizeerd e.o.a. document database, vaak Elastic Search.
Onderhoudbaarheid is belangrijk
Hier zullen meerdere databasetypen geschikt zijn. Maar ik kan me voorstellen dat een klassieke RDBMS-aanpak icm EAV hier goed presteert.
Performance is belangrijk
De grootste performance-obstakel zal zijn zodra je de lijsten wilt kunnen doorzoeken of in lijsten specifieke attributen wilt tonen. Daar komt dan ook de combinatie met Elastic Search of een andere document store bij kijken.
Meertaligheid is in de toekomst belangrijk
Dan is het vooral verstandig dat je je attributen netjes normaliseert. Met name tekstuele attributen die voor meerdere producten gelden wil je zo min mogelijk herhalen. Door ze te normaliseren kan je eenvoudig extra vertalingen toevoegen.
Hier gaan veel NoSQL-stores onderuit doordat veelal verwacht wordt dat je de boel gedenormalizeerd opslaat. Een extra taal per attribuut wordt dan erg lastig, tenzij die database ook ondersteuning heeft voor een zekere mate van normalisatie.
In de RDBMS+ES oplossing zou je per taal een losse ES-collection kunnen bouwen en zo automatisch de juiste vertalingen hebben tijdens het zoeken.
Consistente/correcte attribuutnamen en waarden zijn belangrijk
Dat maakt kunnen normaliseren extra belangrijk

Sommige attributen hebben meerdere waarden
Dat zal je dan op voorhand in je EAV-model moeten meenemen. Zolang je geen unique constraint op de combinatie van product+attribuuttype zet, zou je dat gedrag vanzelf moeten krijgen

Producten moeten eenvoudig met elkaar vergeleken kunnen worden, ongeacht de productsoort
Dat is denk ik niet zo relevant voor de opslag. Uiteindelijk zit het er dik in dat je dat soort vergelijkingen toch wel in je applicatie moet doen, waarbij het dus vooral belangrijk je
in memory makkelijk kan vergelijken (bijvoorbeeld door de attributen in een hashmap te stoppen). Hoe dat in een database opgeslagen zit is daar eigenlijk nauwelijks relevant voor.
Als je van plan bent vele producten met elkaar te vergelijken (bijv een lijstje met vergelijkbare producten), dan wordt het natuurlijk weer een ander verhaal. Maar daar hebben diverse databases dan weer wel ondersteuning voor, iig Elastic Search kent een 'more like this'-functie.
M'n initiële gedachte was om een EAV-achtige structuur toe te passen, maar al snel bleek dat een dergelijke oplossing tal van nadelen heeft. Zo wordt het onmogelijk om te garanderen dat de database consistente data bevat.
Maar is dat een onacceptabel probleem? De enige die volgens mij echt lastig is om te garanderen, is het garanderen dat een product alleen de voor dat type product bedoelde attribuut heeft. De beschikbare type attributen kan je domweg met een tabel vastleggen en via FK's forceren. De eventuele keuzeopties bij een attribuut kan je ook op die manier vastleggen (hoewel het afdwingen dat de keuzeoptie daadwerkelijk bij het type attribuut hoort wel weer lastiger is).
Ik lees overal dat een aparte tabel per productsoort de voorkeur heeft. Ik zie de voordelen van een puur relationele structuur, maar is dit enigszins te onderhouden... Betekent dit dat er in Laravel (waarin de applicatie geschreven wordt) voor iedere productsoort een migration en model moet worden aangemaakt? Is dit een wenselijke situatie?
Dat klinkt als een erg bewerkelijke manier van werken en met honderden productsoorten ook als een onaagename beheerstaak... Je moet dan sowieso database aanpassen bij elke nieuwe productsoort en/of elk nieuwe type attribuut. Ga er maar vanuit dat je attributen ook wilt kunnen toevoegen, aanpassen en verwijderen. En misschien wil je ook wel je producten zelf een keer aanpassen, dan moet je zelfs al die honderden tabellen modificeren.
Dit klinkt me in ieder geval niet beter dan de EAV-oplossing waarbij je je database 1x hoeft op te zetten en daarna vrijwel ongelimiteerd attributen en productsoorten kunt aanpassen of toevoegen.
[
Voor 4% gewijzigd door
ACM op 28-08-2016 11:48
]