webForumDet fria alternativet

Normalisering.

10 svar · 925 visningar · startad av Gladh

GladhMedlem sedan maj 20013 024 inlägg
#1

Jag sitter och designar en databas för ett projekt som jag skall påbörja och undrar hur långt ni brukar dra er normalisering och hur mycket dubbellagring av data som ni tillåter när normaliseringen går "för långt".

Om jag tittar på designen så ser den rätt bra ut för att motsvara kraven som jag har, men när jag sedan skall hämta ut infromationen så har jag idagsläget 7 Inner Joins och då har jag nog bara hämtat ut data från hälften av tabellerna (som jag har idag) och jag har kommer garanterat fylla på med fler tabeller senare :(

Misstänker att en massa joins drar ner prestandan jämfört med att få mer data i tabellerna, men det är f-n inte snyggt med 5 rader som ser likadana ut och där det endast är 1 kolumn som är ändrad x(

Man kan ju lösa det genom att hämta informationen i fler omgångar, men då systemet kommer var en client-server lösning så är det ju inte så trevligt med många små anrop.

Hur brukar ni göra?

dbDesign.png
GeinMedlem sedan sep. 20004 849 inlägg
#2

Intressant! Det finns knappast ett enda sätt som alltid är bäst. Man måste nog se till vilka krav som ställs på projektet. Är prestandan enormt viktigt? Kommer dina joins att påverka systemet negativt? Du kanske upplever det som många men det är inte säkert att det får någon märkbar negativ effekt på systemet. Glöm inte vikten av att ha organiserad data, vilket du per automatik får genom att normalisera.

Nu har jag dock inte speciellt många projekt i ryggen så jag kanske ska akta mig för att uttrycka mig för starkt. Nyligen var jag med i ett projekt att installera Bind (DNS-tjänst) tillsammans med en komponent för att dynamiskt ladda in zoner. Den databas som togs fram var långt ifrån normaliserad (jag vet inte ens om den klararade av 1NF) men vi valde att inte normalisera den för att uppnå maximal prestanda i DNS-tjänsten.

GladhMedlem sedan maj 20013 024 inlägg
#3

gein skrev:

Är prestandan enormt viktigt?

Tja det rör ju sig inte om ett realtidsprojekt eller ett spel i tredjeperson :)

Men visst är prestandan viktig, men man kan gått vänta en sekund extra på datan utan att bli allt för frusterad. Och visst så är det viktigt att organisera datan därför har jag lagt upp det som jag gjort, men man börjar ju undra om det verkligen blir rätt när man måste skriva en 10-12 Joins för att plocka ut den igen. Har för mig att jag läst att om man har mer än 3-4 joins så bör man denormalisera datan för att inte tappa för mycket i prestanda. Men samtidigt så har jag lite svårt att se vad det är som jag skall denormalisera också, möjligtviss skulle man kunna ta bort att Language Tabeller och lägga den information i sina respektiva tabeller, det skulle ju hjälpa en del... (desutom betydligt lättare att hämta ur information med ADO.NET EntityFramework som jag tittat på).

- M

clarkbonesMedlem sedan feb. 20012 693 inlägg
#4

Jag jobbar nu med en stor databas (100 GB). Man får huvudvärk bara av att titta på dess diagram. Den är extremt normaliserad. Vi har nästan inga Updates, eller deletes. Bara nya inserts hela tiden. På så sätt finns hela historiken sparad. Det har sina fördelar i dataintegritets syfte, men att skriva SQL mot denna databas blir förstås rätt omständligt och tidsödande. Det finns dock kompletterande denormaliserade tabeller som förenklar arbetet.

Detta skulle inte funka om det vore en rapportdatabas. I denna databas så tittar man framförallt på enskilda poster, och skapar nya enskilda poster. Hela rapport/analysfunktionaliteten ligger andra databaser som matas med info från "transaktionsdb:n".

CompusaMedlem sedan jan. 20022 952 inlägg
#5

Jag brukar normalisera till "BCNF" dvs något striktare än tredje normalformen. Om det blir många krångliga frågor så kan du ju förenkla det hela med att använda vyer som exempelvis representerar dina vanligaste "joins".

Just like functions (in programming) provide abstraction, views can be used to create abstraction. Also, just like functions, views can be nested, thus one view can aggregate data from other views. Without the use of views it would be much harder to normalise databases above 2nd normal form. Views can make it easier to create lossless join decomposition.

clarkbonesMedlem sedan feb. 20012 693 inlägg
#6

Compusa skrev:

Jag brukar normalisera till "BCNF" dvs något striktare än tredje normalformen. Om det blir många krångliga frågor så kan du ju förenkla det hela med att använda vyer som exempelvis representerar dina vanligaste "joins".

Views är bra, men det löser inte alla prestandaproblem.

CompusaMedlem sedan jan. 20022 952 inlägg
#7

Nej det löser inte alla problem men det är en bra början då man kan förenkla sina SQL-frågor avsevärt, vilket jag uppfattar att Gladh bland annat var intresserad av? Indexering av de attribut som används vid "joins" skulle kanske kunna vara ett steg i rätt riktning för att öka prestandan.

Skummade väldigt snabbt igenom denna artikeln och den verkade väldigt intressant...

NickemannenMedlem sedan aug. 20003 524 inlägg
#8

Mycket language tabeller? Är det data som uppdateras ofta? Finns det möjlighet att lägga dessa hos varje klient i resourcefiler?

Har man dubletter av data så kan det ju lätt bli inkonsekvent data.

Jag hade nog kört på många joins och om det blir för dålig prestanda öka på med bättre hårdvara, alternativt bygga om senare.

Men just det att det är en client - server så vill man väl inte skicka över för mycket data hela tiden heller?

GladhMedlem sedan maj 20013 024 inlägg
#9

clarebones:
Intressant, som du kanske kan lista ut av namnen på tabellerna så handlar det om produktdatabas, men ett tillbehörande kassa och lagersystem. Visst kommer det komma krav på rapporter, vem vill inte ha rapporter av försäljning och hur visa produkter går osv osv.. Men precis som du säger så kan man ju lösa detta med batchs som kör nattetid när butikerna är stängde för att denormalisera in de i nya tabeller för att öka prestanda till rapporterna.

Compusa:
Ja att förenkla via vyer är ju smart, eller egentligen förenklar du ju inte eftersom vyn blir komplex att skriva, men det blir enklara att fråga databasen! Men det jag är mest bekymrad över är prestanda hittarna som blir med 10-12 joins i mot olika tabeller. Och bara för att göra det ännu mer bekymmersamt så kommer mina nycklar inte vara integers utan GUIDs, eftersom de kommer underlätta extremt mycket när visa klienter skapar poster i databasen och är offline :) Vilket kanske inte är det mest optimala ur prestandasynpunkt...
Angående Indexen... o ja, de kan göra underverk om man sätter de på rätt ställen, jag har sett frågor som tagit minuter att hämta ut som kommit ner på tiondelssekunder när man fått till indexen korrekt. Och inte bara indexen utan vilken tabell som skall joina mot vilken, tydligen så gör det mycket på prestanda vilken tabell som man sätter på vilken sida joinen, så det blir till att plugga på lite där...

Nickemannen:
Jag har faktiskt beslutat mig för att slå ihop lanugagetabellerna med deras motsvarande tabell, det blir ju lite dubbelinformation, men inte speciellt mycket, men det kommer dra ner på joinsen en del.

- M

GladhMedlem sedan maj 20013 024 inlägg
#10

clarebones skrev:

Vi har nästan inga Updates, eller deletes. Bara nya inserts hela tiden. På så sätt finns hela historiken sparad. Det har sina fördelar i dataintegritets syfte

Har ni inga update och delete i tabellern, för jag har jobbat mot databaser där man ALDRIG ändrade/tog bort en post, utan man bara gjorde den inaktuell, och istället så la man en ny post med den nya information och gjorde den aktuell, och när man skulle göra en delete så gjorde man posten inaktuell. På det visset så fanns all data kvar i tabellen och man kunde följa precis vad som hade hänt historikmässigt vilket i och för sig är ett krav i danmark för banker, all data skall sparas i minst 5 år, inget får tasbort om det är mindre än 5 år gammalt.

Det var mycket smidigt, man satte 2 extrafält på tabellen som hete: TechnicalDeleted/TechnicalCreated och var av typen datum. Som default satte man TechnicalCreated till dagensdatum och TechnicalDeleted till '9999-12-31 23:59:59' och om man ändrade med en update eller insert fråga så tog en trigger hand om det och satte TechnicalDeleted till dagensdatum på aktuell rad, och skapade sedan en ny post med den nya information i och technicalCreated till dagens datum.

Mycket smidigt, men som sagt det blir ju en del data i databasen om man aldrig tar bort något från den och lägger till en ny rad för varje update och delete man gör :)

- M

clarkbonesMedlem sedan feb. 20012 693 inlägg
#11

Ja, den lösning som du beskriver är snarlik den jag arbetar med i det avseendet.

För rapporter & analys bör du använda en OLAP-databas som t ex Analysis Services. Tänk dig att någon på ekonomiavd vill veta hur mycket butiken sålt för ett visst år.

Detta är ju summan av alla enskilda inköp, vilken i en stor matbutik lär vara miljoner. Att summera detta kan ju ta lång tid i en OLTP-databas som SQL Server. Med en OLAP-databas kan rapporten vara färdig inom en sekund, eftersom data försummerats under nattens överföring mellan OLTP-databasen och OLAP-databasen.

http://en.wikipedia.org/wiki/Online_analytical_processing

130 ms totalt · 3 externa anrop · cache AV · v20260731051352-full.56cc9887
0 ms — hämta statistik (cache)
0 ms — hämta forumlista (cache)
127 ms — hämta tråd, inlägg och bilagor (db)