|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Senior Member
Iscritto dal: Oct 2004
Città: Messina
Messaggi: 684
|
[Mysql] Dubbio sui campi null
Ho una tabella che contiene uno user id di tipo long ed un campo di tipo binario che mi indica il tipo di user id. user id è la sola chiave
Devo esprimere delle amicizie, quindi è necessaria una associazione m a n con se stessa, che produrrebbe un'altra tabella. Non sarebbe meglio avere una sola tabella con le colonne uid1, uid2, tipo impostando il tipo solo per la prima occorrenza di uid1 e per le altre occorrenze tutte a NULL e risparmiando una tabella che avrebbe l'elenco degli uid (inutile) ? ...oppure avere milioni di campi a null destabilizza lo schema logico ? cosa conviene ? (il mio db sarà molto grande) ![]() |
![]() |
![]() |
![]() |
#2 |
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Io ti consiglio di separare le entita' dalle relazioni, come classicamente si insegna (e si fa)
Quindi la tabella entita' delle persone, con chiave primaria l'identificativo e tuttli gli attributi correlati (come quello dei tipi) e una tabella per la relazione amicizia, con 2 campi che entrambi puntano all'identificativo della tabella entita', entrambi in chiave, con magari attributi relativi all'amicizia, se presenti (data del primo incontro, etc.) Devi ancjhe chiederti come trattare la "matrice associata delle amicizie" Se A e' amico di B, allora anche B e' amico di A? Quante entry mettiamo per questa amicizia, una oppure 2?
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
![]() |
![]() |
![]() |
#3 | |
Senior Member
Iscritto dal: Oct 2004
Città: Messina
Messaggi: 684
|
Quote:
ovviamente a amico di b = b amico di a così risparmio di scrivere parecchi milioni di righe che dicono la stessa cosa |
|
![]() |
![]() |
![]() |
#4 | ||
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
In prodotti commerciali solitamente si tende ad avere solo strutture normalizzate, affiancate da strutture denormalizzate che si potrebbero ricostruire da zero interrogando le strutture normalizzate, di sola lettura, per questioni di performance, e automaticamente rinfrescate quando si aggiornano le strutture normalizzate. Quote:
Una domanda come Chi sono tutti gli amici di 'Tizio' Ha bisogno di una query piu' o meno complessa, a seconda di cosa avrai deciso di inserire nel database. Prova a scriverla, e ti diro' di piu'. Posso anche sbilanciarmi a dire che per fare una cosa ben fatta e ben ottimizzata lo spazio totale speso per la soluzione simmetrica (ovvero inserire sia A-->B e B-->A) rischia di essere addirittura piu' basso che quello speso per la soluzione asimmetrica.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. Ultima modifica di gugoXX : 06-05-2009 alle 16:13. |
||
![]() |
![]() |
![]() |
#5 | |
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Quote:
![]()
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
|
![]() |
![]() |
![]() |
#6 |
Senior Member
Iscritto dal: Oct 2004
Città: Messina
Messaggi: 684
|
è vero. non ci avevo pensato.
in effetti dovrei fare: Codice:
SELECT uid2 FROM Amici WHERE uid1='uidlong' UNION SELECT uid1 FROM Amici WHERE uid2='uidlong' ...conviene ragionare in base a quale risorsa scarseggia di più spazio su disco o tempo... e anche in fase di scrittura dovrò andare a fare un controllo in più. allora non mi conviene più ![]() trovo interessante il discorso dei prodotti commerciali, a patto di avere molto spazio... ps. mi fai da consulente per la tesi ? ![]() |
![]() |
![]() |
![]() |
#7 |
Senior Member
Iscritto dal: Oct 2004
Città: Messina
Messaggi: 684
|
|
![]() |
![]() |
![]() |
#8 | |
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
Non solo il tempo e' piu' lungo, ma addirittura intendevo sbilanciarmi sul fatto che anche lo spazio risparmiato risulterebbe essere meno di quanto si pensi. Mi spiego. Abbiamo gia' deciso che la PK della tabella debba essere composta, formata da entrambi i campi uid1 e uid2. Per ottimizzare una query tipo Codice:
SELECT uid2 FROM Amici WHERE uid1='uidlong' Ma abbiamo gia' deciso di avere la chiave primaria composta. L'inidice migliore quindi e' automatico, ed e' appunto (uid1, uid2), proprio in questo ordine. In tal modo l'engine, per risovlere questa query, il motore andra a leggere proprio (e solo) l'indice sulla PK, scorrendo il BTree in ordine. Si chiama RangeScan. Se la tabella dovesse occupare 20MB, ne consegue che anche questo indice qui occuperebbe proprio 20MB, essendo composto da tutte e sole le colonne della tabella in questione. Anche gli indici occupano spazio... Ma la nostra query pero' ha anche il verso opposto. Per risolvere la WHERE uid2='12354' l'indice di prima non ci serve affatto (non e' proprio del tutto vero, Oracle per esempio potrebbe usarlo con una tecnica chiamata SkipScan, ma che e' bene usare collateralmente piuttosto che intenzionalmente) Per poter ottimizzare tale WHERE occorre aggiungere un altro indice. l'indice con le colonne opposte, ovvero (uid2, uid1). PS: Sarebbe quasi sufficiente anche solo un indice aggiuntivo sulla colonna uid2, ma il tempo di query ne soffrirebbe, essendo che il motore, per andare a trovare tutti i valori uid1 per il dato uid2 dovrebbe prima accedere all'indice (di nuovo Range Scan), ottenere gli indirizzi dei record che interessano, e con ciascuno di questi andare a leggere la riga corrispondente direttamente nella tabella per ottenere i valori cercati. La soluzione ottimizzata migliore sarebbe quindi dotare la tabella proprio dell'indice aggiuntivo, (uid2,uid1), che permette la risoluzione di questa seconda parte di query di nuovo leggendo solo i dati dell'indice senza riaccedere alla tabella sottostante. Ma cio' equivarrebbe ad aggiungere altri 20MB di spazio... Ergo secondo me e' meglio raddoppiare la tabella rendendola simmetrica 20MB+20MB di tabella e 20MB+20MB di PK piuttosto che tenere la soluzione asimmetrica 20MB di tabella, 20MB di PK e 20MB di indice aggiuntivo, ma con query decisamente piu' complesse, piu' difficilmente leggibili e meno performanti. (Per fare la UNION finale il motore deve anche riordinare il risultato per prendere solo i DISTINCT, un altro O(N LOG N), dove pero' almeno sperabilmente tali risultati saranno pochi. Dipende dai dati.)
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
|
![]() |
![]() |
![]() |
#9 |
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
![]() Per curiosità, queste conoscence specifiche sono dovute a esperienze professionali oppure tuoi approfondimenti personali?
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
![]() |
![]() |
![]() |
#10 |
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Beh, diciamo che e' un buon bilancio tra le due cose.
Diciamo che le aziende che ho incontrato mi hanno dato la possibilita' di approfondire questi temi sia per mia passione che per loro utilita'... Relativamente ai Database ho lavorato in Oracle per 1 anno e mezzo, ho una certificazione Oracle e una SqlServer, ma queste certificazioni ho potuto studiarle sfruttando anche tempo aziendale, facendo domande direttamente alle fonti e soprattutto i costi delle certificazioni sono stati pagati dalle aziende stesse. E poi tante ricerche sulle ottimizzazioni perche' i tempi delle query sono sempre lenti. Qualunque query per qualunque problema. E' una legge di Murphy. Questo e' uno dei motivi per cui a chi mi chiede se un master dopo l'universita' vale la pena io normalmente dico di no. Secondo me e' meglio una buona azienda che da' gia' una buona impornta professionale, magari condita da esperienze come le certificazioni che le aziende stesse sono piu' che propense a stimolare. E il Master e' come se te lo ritrovassi in tasca. (almeno nel nostro campo)
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
![]() |
![]() |
![]() |
#11 | |
Senior Member
Iscritto dal: Oct 2004
Città: Messina
Messaggi: 684
|
Quote:
10 milioni, in media 100 amici a persona.... ![]() p.s.: sei un Dio. |
|
![]() |
![]() |
![]() |
#12 |
Senior Member
Iscritto dal: Nov 2000
Città: Bussero (MI)
Messaggi: 1263
|
però con una soluzione simmetrica in inserimento devi fare 2 insert invece che una.
se il rate di nuovi inserimenti fosse maggiore del rate di letture allora il discorso performance potrebbe cambiare. Dipende da cosa deve fare la tua applicazione. |
![]() |
![]() |
![]() |
#13 | |
Senior Member
Iscritto dal: Oct 2004
Città: Messina
Messaggi: 684
|
Quote:
Poi fra l'altro ho pensato che non c'è tutto questo guadagno, perchè le righe saranno la metà gestendo in modo non simmetrico. Fare una sola select su 200 Milioni di righe o fare 2 select con una UNION su 100 Milioni di righe non è la stessa cosa ? ![]() [ho letto meglio il post in cui si parlava degli indici, non avevo capito] Ultima modifica di Lakaj : 07-05-2009 alle 16:31. |
|
![]() |
![]() |
![]() |
#14 | |
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
Questo perche' quando accedi ad una tabella via indice, sperando in un RANGE SCAN, i dati saranno pronti immediatamente dopo avere trovato il primo e l'ultimo record nell'indice, e la loro restituzione (fatta salva la lunghezza del risultato) e' praticamente gratuita. Ma tali primo e ultimo record occorre trovarli, per ricerca tipicamente dicotomica su indice ordinato, il cui costo e' noto essere O(Log N). Ipotizzato quindi 10.000 di record nel caso non simmetrico, avrai quindi un costo di Log(10000) + Log(10000) mentre nel caso simmetrico Log(20000) e vinci comunque sempre. Poi nel primo caso ci sarebbe anche il postprocess della UNION, che supponiamo gratuito essendo come penso molto basso il numero di record restituiti dalla query. Altrimenti si peggiora ancora a favore della soluzione simmetrica.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
|
![]() |
![]() |
![]() |
#15 | |
Senior Member
Iscritto dal: Oct 2004
Città: Messina
Messaggi: 684
|
Quote:
Però un inserimento in più per garantire simmetria quanto mi costa ? In simmetria avrei 2 insert subito (da parte di x) in cui dico: x amico y y amico x poi però dopo arrivo a y, che ancora non sa se x l'ha messo come amico, perchè magari y è stato messo in lista dopo... quindi scatta la SELECT quindi 2 insert + 1 select (veloce) mentre nel caso asimmetrico avrei 1 insert + 1 select (lenta) Ma questa insert in più che prestazioni ha ? io sapevo che le scritture erano più lente delle letture, del resto comportano un aggiornamento degli indici... |
|
![]() |
![]() |
![]() |
#16 | ||
Senior Member
Iscritto dal: Nov 2008
Messaggi: 411
|
Quote:
Una base dati totalmente priva di ridondanze non esiste, esistono però DB progettati bene e DB progettati male, dipende molto dal caso specifico. Quote:
__________________
![]() |
||
![]() |
![]() |
![]() |
#17 | |
Senior Member
Iscritto dal: Oct 2004
Città: Messina
Messaggi: 684
|
Quote:
...in fondo lo spazio non è un bene che scarseggia nel 2009, il tempo si. meglio qualche giga in più, purchè la cosa non sia esponenziale... ![]() |
|
![]() |
![]() |
![]() |
#18 | ||
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
![]() Le insert non pensano tanto fino a che non si giunge a qualche centinaia di milione di record, e comunque normalmente le ottimizzazioni sono piu' sulle letture (presumibilmente tante) che sulle scritture (poche). Certo che se inserisci solo e non leggi mai, come nei DB di log, allora le scritture diventano importanti. Quote:
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
||
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 09:38.