Newsgroup: it.comp.software.database
Titolo: Foreign key e normalizzazione, quale soluzione?

Buongiorno a tutti...
Un collega afferma che un db strutturato in maniera a suo dire
"normalizzata" migliora le performance soprattutto
con grosse mole di dati.
Il punto è che lui dice che data una tabella con un numero definito di
colonne che contengono la chiave di un'altra
tabella è meglio spostare tali dati su un'altra tabella. Mi spiego
meglio esponendo il caso specifico.
TABELLA: ID_SOGGETTO, DESC_SOGGETTO, ID_CONTO_A, ID_CONTO_B,
ID_CONTO_C, ID_CONTO_D, (altri campi che non c'entrano nulla)
I campi "ID_CONTO_X" sono in foreign key verso la tabella dei conti,
dalla quale in visualizzazione andiamo a
prendere le descrizioni e altre informazioni. Lui afferma che creare
una seconda tabella che contenga l'elenco di
sottoconti (anche se questi sono in numero definito e limitato)
migliori le performance di risposta del db.
Io ho la sensazione che invece sia il contrario, qualcuno sa dirmi chi
ha ragione ed eventualmente come dimostrarlo?
Grazie


zac
IMHO dipende dal db...ma anche secondo me...recuperare i dati in una
tabella "semplice" si fa prima!
Cmq per toglierti il dente
prendi il tuo db e creati un programmino di stress
io lo saprei fare in vb.net...ma è lo stesso in qualsiasi linguaggio:
Caricati la tabella "semplice1 e semplice 2"...e quella "Master
+linkata"...con un po di dati...
poi...
azzera timer (tick in dotnet)
start timer
fai un ciclo di interrogazioni random su quella semplice1 e 2
Sarà una cosa del tipo
1 query recupero testata....2 query recupero sottoconti
stop timer
Stampa timer
lo stesso per
Master + linkata...solo che la query sarà singola
se il tuo "programmillo"...poi riesci a farlo eseguibile...ti puoi
divertire a lanciarlo anche da più postazioni per vedere in caso di
multiutenza che succede!
IMHO dipende dal motore db e da come è settato per ottimizzare le
query.
Ma perdendo l'integrità referenziale...non vai incontro ad altri
casini?
Ossia non ti ritocca far ri-entrare dalla finestra sotto forma di
codice in più...quello che hai buttato dalla porta???
E' davvero così time-critical la vostra situazione ???

 E' davvero così time-critical la vostra situazione ???
Intanto grazie x la risposta... perchè dovrei perdere l'integrità
referenziale? In entrambe le soluzioni ce l'avrei.
Il punto è che hanno chiesto di ottimizzare il db ed è saltata fuori
questa soluzione ma secondo me (a naso)
non è un'ottimizzazione ma piuttosto le prestazioni le peggiorerebbe
(senza contare il tempo speso per rifare i programmi).


Io ho capito che vuoi spaccare in 2 tabelle non vincolate ...e
recuperare con 2 query invece che con una!(allora imho forse qualcosa
puoi spuntare...anche perchè avresti tabelle di dimensioni diverse
come hai detto...anche MOOOLto diverse come grandezza a quanto
scrivi!)
...sono andato oltre il concetto di normalizzazione ed ho capito male
quello che intendeva il tuo collega???
Se devi comunque tenere un vincolo e quindi costringere ad una
elaborazione del vincolo il codice del motore db...tanto vale che usi
il vincolo che ti impone più chiarezza logica (anche perchè il debug o
le modifiche fra 6 mesi toccano a te ...o a un tuo collega!)
cmq....basta provare!
in un ora fai programma e le prove che vuoi!

 in un ora fai programma e le prove che vuoi!- Nascondi testo citato
...a meno che tu non intenda fare un test di stress per tutta la notte
eh!...credo ti basta avere una indicazione se la strada sia
percorribile o meno come cicli di clock trovati/risparmiati...

 - Mostra testo citato -
Il punto è che avrei preferito dare una motivazione tecnica e non una
supposizione confermata da un test.
Tra le altre cose lui ribatteva sul fatto che trattandosi di
un'applicazione web era importante portarsi dietro meno dati, cioè nel
caso in cui fosse compilato uno solo dei 4 campi si risparmiano ben
(sparo) 100 caratteri !!! :-)
Pensa che fortuna eh?! :-) Con tutto il codice html che si porta
dietro saranno quelle info che pesano... secondo me è più pesante poi
da recuperare l'informazione da più tabelle!! Ma non riesco a
dimostrarlo!!!

 ha ragione ed eventualmente come dimostrarlo?
Premetto che imho dipende pure dal DB.
Secondo me trattandosi di master/detail � giusto che ci sia la tabella
Testa e Righe, relazionate fra loro.
Non sono certo di come venga risolta una join a 5 tabelle (master +abcd di
conti), rispetto ad una a 3 tabelle (master, detail, conti). Potrebbe
essere che la seconda sia pi� veloce.

 
chi ha ragione?
dipende...
perche' hai inserito i 4 campi id_conto invece di usare una cross?
con la tua struttura, se vuoi sapere a quanti sottoconti e' associato un 
soggetto tramite query, devi fare cose strane, con una cross basta una 
select con count.
se devi aggiungere un sottoconto (ti hanno detto e firmato col sangue che 
non saranno MAI piu' di 4? mentono!), devi rifare tutta l'applicazione.
vuoi tutto il dettaglio del soggetto, compresa la descrizione di tutti i 
sottoconti su una sola riga?
tralasciando i join che devi ficcare nella query, rivedi la richiesta 
perche' e' una interrogazione poco sensata...
io non vedo vantaggi nella struttura che hai scelto.
ma soprattutto, piuttosto che motivare la scelta di avere una cross table 
(imho la scelta piu' ovvia), devi motivare il perche' inserisci nella 
tabella dei soggetti dei dati che non devono starci .
:-)
-- 
Paolo opg
BE AWARE that this post uses a fake reply-to address
to contact me write to:
janickg ( at ) hotmail ( dot ) com
--

 - Mostra testo citato -
Cerco di chiarire la struttura inventandone una perchè non ricordo i
campi esatti,
poniamo che la tabella sia composta tra le altre cose da:
-ID Fattura
-Importo imponibile
-Sottoconto imponibile (in join con tabella dei sottoconti dove
reperisco la descrizione)
-Importo imposta
-Sottoconto imposta (in join con tabella dei sottoconti dove reperisco
la descrizione)
-Importo errore (non presente su database ma calcolato secondo certe
logiche non utili al discorso)
-Sottoconto errore (in join con tabella dei sottoconti dove reperisco
la descrizione)
-Totale documento
Ora perchè io dovrei pensare di dividere la fattura in due tabelle
fatte così:
Master table:
-ID Fattura
-Totale documento
Child table:
-ID Fattura
-ID di questa tabella indefinibile per me (non so... sottoconti
fattura)
-Importo X
-Sottoconto X (in join con tabella dei sottoconti dove reperisco la
descrizione)
Sul form dovrei poi gestire il fatto che la text importo imponibile
"punti" al campo della child table con ID=1,
la text del sottoconto imposta al campo della child table con ID=2,
ecc... perchè?
Spreco un sacco di tempo a caricare i dati, in più devo fare n join se
voglio utilizzare un'unica query per caricare
il mio BO. Ma il punto critico mio riguarda le prestazioni... non ho
ragione nel dire che peggiorerebbero?
Grazie di nuovo e scusate la mia poca chiarezza :)

 - Mostra testo citato -
più tecnico di un test imho non c'è nulla!
Si adatta al tuo hw...alle tue capacità...al tuo background...in una
parola alla situazione reale!
Anche perchè chiedi (alla fine ho capito il senso....son duro
stasera....sto sverniciando le persiane di casa e i gas mi bloccano
l'unico neurone rimasto)
se 3 join son più veloci di 4...
dovrebbero essere più veloci(son meno cose da controllare e/o
cercare)  ma bisognerebbe avere il sorgente del db e vedere se non
compie ottimizzazioni!...e sperando che ottimizzi!
Non entro nel merito della tabella...
mi voglio fidare che quella struttura sia il meglio possibile...ma chi
ti ha risposto ti dovrebbe aver lasciato plausibili dubbi!
Aggiungo....tanto per sport....
ma che database è?
Access ??? eh eh eh!....non scherzare eh!


ZAC
io ho sempre fatto così!
TAB1
ID fattura
dati testata e tutto quello che vuoi
NO 4 id sottoconto!!!
TAB2
IDsottoconto
tutto quello che vuoi
TABcross
IDfattura
IdSottoconto
relazioni fra tabelle....le metti da te eh!
quando fra 6 mesi ci rimetterai le mani per una
personalizzazione...ringrazierai!

 mole di dati.
Senza entrare nel merito se la struttura e` normalizzata
correttamente, l'affermazione in linea di principio e` giusta;
riducendo la ridondanza, infatti, si sfrutta meglio la memoria
(sia la cache che il disco), e tale fenomeno si palesa quando
la memoria e` completamente piena (appunto con db "grandi").
Invece finche` il db sta completamente in ram, e` molto difficile
notare qualcosa.
Inoltre, gli rdbms sono ottimizzati per gestire db normalizzati,
per i quali esistono varie strategie di tuning. 

 
no, secondo me non hai ragione. ^^
una query sola con 4 join tutti con la stessa tabella, non sono sicuro 
sia piu' efficiente di 2 query separate con un solo join. all'aumentare 
del numero di righe, molto probabilmente ti troveresti con un pachiderma 
zoppo che arranca a ogni query.
pero' non ho dati reali da darti, perche' effettivamente non ho mai usato 
una struttura come la tua ^^
in ogni caso, parti dalla struttura del db e non dall'interfaccia, 
altrimenti ne vieni fuori quasi sicuramente con una struttura da incubo 
che ti creera' piu' problemi che vantaggi.
se hai una fattura e 4 sottoconti associati, volere tutte le info su una 
riga e' una castroneria, imho.
hai una testata, un corpo (le righe di dettaglio), i sottoconti 
associati, il cliente a cui si riferisce la fattura.
perche' dovresti ammassare tutto in una sola tabella?
sono entita' distinte, quindi una tabella per ognuna di loro e i 
collegamenti li fai tramite cross.
tanto per fare un esempio, nei report usati per generare le fatture, di 
solito c'e' un sottoreport per ogni 'entita'' e nel report principale hai 
solo i dati di testata (data, numero, codice cliente). tutto il resto 
viene ripescato dalle tabelle collegate tramite query semplici sulle 
chiavi primarie.
n query semplici sulle chiavi primarie e non una megaquery che estrae 
tutto in un solo passaggio.
se sul form principale hai un campo text per ogni sottoconto, devi imho 
rivedere l'interfaccia.
io metterei i sottoconti in una sottomaschera che prende i dati tramite 
una query con la chiave 'idfattura' della form principale.
come mai le prestazioni sono cosi' critiche?
se sono cosi' critiche, non val la pena di spendere un po' di tempo in 
test sul campo piuttosto che discuterne e basta?
due tabelle con un milione di righe e vedi subito se la tua soluzione si 
siede o regge.
;-P


 Grazie
in mysql in alcuni casi consigliano le function o le stred procedure
per rispondere in meno tempo
scusa io ho ID_CONTO_(n) come lo risovi se ho 19 conti correnti ?
altra cosa IMPORTANTE e' che interrogazione fai ?
cioe voglio il conto o gli utenti ?
(dipende anche dall'applicazione)
cerco l'utente (1 query)
voglio il conto dell'utente (2a qury)
visulaizzo il conto richiesto (3a)
voglio i movimenti dell'utente su tutti i conti in un colpo ?
utente e conti intestati in una query ?
da questo dipende la truttura del db