bee-es schreef op vrijdag 09 december 2005 @ 13:10:
In deze situatie gaat het niet om het uitnormaliseren van adressen om 1 adres met meerdere klanten te delen volgens mij.
Een heel geldige reden kan zijn dat je bij een relatie meerdere adressen hebt (postadres/factuuradres/aanmaningsadres/kerstkaartadres/magazijn/etc). In dat geval lijkt het me toch wel handig om ze in een aparte tabel te zetten (ipv PostadresStraat, FactuuradresStraat, AanmaningsadresStraat....)

Dit is zeker het geval als je bijv. een document wilt genereren, waarbij de gebruiker een adres uit een lijstje moet kunnen selecteren.
Wat jou handig lijkt, waar is dat op gebaseerd? Want hoe worden die adressen ingegeven? In een 'klanteninvulscherm' ? Indien ja, daar staan textboxen op voor straat e.d.? Dan heb je geen reet aan je aparte tabel.
bigbeng schreef op vrijdag 09 december 2005 @ 13:25:
[...]
Je doet meerdere inserts/updates achter elkaar, dus je moet toch met transactions werken. Een lock hoeft in principe alleen maar read-only te worden vastgelegd, dus het enige wat je aan scalability verliest is bulk update/insert met meerderen tegelijkertijd. Met transactions kun je zelfs zonder locks werken. Dit betekent wel grotere kans op fouten als gevolg van transaction commits die niet werken, maar goed, dit kun je ook weer ondervangen.
Je hoeft mij niets te vertellen over transacties hoor
Maar wat je zegt is volledig niet relevant. Thread A en thread B. Thread A kijkt in de tabel. Geen 'straat ABC'. Dan gaat thread B record 1000 wijzigen, van 'straat XYZ' in 'straat ABC'. Dan gaat A 'straat ABC' inserten. *poef*. M.a.w.: test is overbodig, gewoon inserten en dan de fout afvangen en terugleiden naar de gebruiker dat het adres al in gebruik is (of anders afhandelen, whatever er is besloten voor dat geval). Die test stopt men er soms in om die fout niet af te vangen, maar dat is dus onzin, die komt geheid.
Het gaat mis omdat A test op een waarde die NA de test maar VOOR de insert wordt toegevoegd aan de tabel in een andere thread. A kan locken wat A wil, maar dat helpt niets, want A zou dan alle rows moeten locken pal voor de test tot aan pal na de insert. Immers, op geen andere manier kan A voorkomen dat B iets wijzigt in een _ANDERE_ row dan A mee gaat werken.
Transacties zonder locks bestaan overigens niet, tenzij je een mode gebruikt waarin je een snapshot krijgt van de set waarop je modificaties uitvoert.
En gezien het feit dat we niet genoeg weten van het systeem, is moeilijk in te schatten of meerdere mensen op hetzelfde record tegelijkertijd kunnen veranderen. Als dit niet zo is, dan is transactions gebruiken in principe voldoende beveiliging en de kans op foutmeldingen als gevolg van commits minimaal.
Het ging om wat juist was. Testen en dan doen is niet juist in dit geval want het levert fouten op. Dan kan dan in jouw ogen wel 'minimaal' zijn, maar dat zijn zg. 'famous last words', die je altijd opbreken. Daarom moet je zorgen dat je software in 100% van de gevallen foutloos is, in theorie, en met tests checken of je software implementatie(!) van je ontwerp inderdaad een juiste implementatie is. Indien ja, dan is je software in de praktijk ook 100% foutloos.
Wat betreft uitnormaliseren van het adres, dat hangt af van de kans dat er nog een 3e/4e/5e etc adrestype bijkomt. Als dat aan de orde is kan het je programmeerwerk schelen door een extra adrestype in je database toe te voegen die dan automatisch door je systeem wordt opgepakt. Als je het allemaal in 1 tabel prakt dan heb je in zo'n geval een datamodelwijziging en een applicatiewijziging te pakken.
Adrestype is in het geval van 'adres' een attribute van de relatie (objectified):
[CustomerID* | AdresID* | AdresType]
Echter wie het zo uitnormaliseert zoals hierboven geschetst heeft geen voordeel van die normalisatie want Adres wordt niet hergebruikt. Dit is het gevolg van hoe 'adres' in de praktijk wordt toegepast. In theorie is het wel herbruikbaar natuurlijk, het is een entity als alle andere, maar de attributes van adres neigen naar een 1:1 relatie met customer, waardoor je customer en adres kan mergen.
En tenslotte wat betreft thread safety: je kunt toch gewoon een thread maken die verantwoordelijk is voor het verwerken van veranderingen in je klant/adres deel van de applicatie? Op die manier kan er steeds maar 1 iemand tegelijkertijd een wijziging daarop doorvoeren. Dit gaat wel ten koste van scalability, maar gaat thread safety dat niet altijd als het gaat om niet-atomaire acties die "tegelijkertijd" moeten worden uitgevoerd?
Die thread krijgt het dan wel erg druk en is direct de bottleneck van je pipeline naar / van de db.
Beter is functionality locking, waardoor gebruikers alleen die elementen kunnen wijzigen nadat ze die eerst hebben geclaimd. Zodoende kun je het werk wat gedaan moet worden beter structureren en krijg je een hogere efficiency, want persoon A gaat dan niet iets wijzigen aan data die persoon B ook net zit te wijzigen want in dat geval kan B beter die wijziging van A OOK doen en A iets anders. Dat scheelt dataverlies door een of ander concurrency mechanisme (optimistic/pessimistic, maakt niet uit)
[
Voor 76% gewijzigd door
EfBe op 09-12-2005 17:56
]