Newsgroup: it.lavoro.informatica
Titolo: [database] schema efficiente per avere uno storico dei prezzi

ho la necessità di importare quotidianamente i listini dei fornitori e 
di tenere traccia di eventuali variazioni
 
ad esempio conoscere in un dato momento gli articoli il cui prezzo è 
variato rispetto a sei mesi fa (o rispetto ad una data specifica)
oppure quali sono i prezzi degli ultimi dieci giorni oppure quali erano 
i prezzi dalla <data> alla <data>
 
attualmente (su mysql) viene usata una singola tabella con questa 
struttura:
 
CREATE TABLE `products` (
  `file_date` date NOT NULL,
  `supplier_id` varchar(128) NOT NULL,
  `description` varchar(255) DEFAULT NULL,
  `cost` double(10,2) DEFAULT NULL,
  PRIMARY KEY (`file_date`,`supplier_id`),
) ENGINE=InnoDB;
 
i tempi di lettura delle informazioni sono inaccettabili
 
una query come
 
SELECT * FROM products AS po WHERE po.supplier_id='CODICE' ORDER BY 
file_date DESC LIMIT 0,10;
 
impiega 12 secondi
 
fortunatamente questo sistema esisteva già :) e vogliono ampliarlo per 
supportare l'importazione da fornitori multipli ma anche per 
velocizzare il tutto
 
ho una macchina linux a disposizione quindi posso passare da mysql a 
qualunque altro database engine senza particolari problemi
 
siccome è la prima volta che mi trovo a dover consultare un archivio di 
questo tipo (in cui le date giocano un ruolo fondamentale) sono alla 
ricerca di letture consigliate, schemi da cui prendere spunto e 
compagnia cantante
 
grazie anche solo della lettura
 
 
 
-- 
Ti dirò una cosa Vanessa un proiettile ha lo stesso suono in ogni 
lingua, quindi ficcati nel culo una calibro nove!!!
 
 

 qualunque altro database engine senza particolari problemi
 
Bisognerebbe avere anche un'idea di che quantità di dati stiamo parlando; ecco il motivo per cui devi prendere la mia opinione con le dovute molle.
 
Io prima di tutto proverei a giocare con gli indici: ne metterei uno per file_date, uno per supplier_id. Tempi così lunghi non sono assolutamente normali.
 
-- 
Ciao!
Luca

 dovute molle.
 
niente endorsment :)
 
-- 
Soprano

 normali.
 
l'alter table è in esecuzione da venti minuti :)
 
provo e ti faccio sapere
 
per il momento grazie
 
-- 
vuoi mettere l'emozione di dormire davanti alla saracinseca abbassata 
di mediaworld insieme ad altri disadattati, dopo una cena frugale 
davanti al fuoco?
anzi no, il fuoco non si può accendere
facciamo che ceniamo a merendine
 
 

 grazie anche solo della lettura
 
pre
 
-- 
Soprano

 pre
 
ma quanto sei sciocchino? quanto?
 
-- 
la differenza è che lei me la chiaverei e da cieca non è detto che non 
ci stia
 
 

 provo e ti faccio sapere
 
Aggiungo uno spunto generale che magari può servire. Dai un occhio anche a quante risorse sono allocate a quel dbms in termini di RAM e processore.
 
-- 
Ciao!
Luca

 prezzi dalla <data> alla <data>
 
l'inefficienza secondo me è dovuta al fatto che l'indice della pk è 
invertito rispetto alla selettività che ti serve, o cambi l'ordine di 
file_date, supplier_id oppure crei un altro indice.
 
per il resto la query corretta è qualcosa del tipo (da provare, 
ovviamente):
 
WHERE po.supplier_id='CODICE' 
and po.file_date = (select max(po1.file_date)
from products po1
where po1.supplier_id = po.supplier_id
and po1.file_date <= <data> )
 
dove <data> è la data di cui vuoi sapere il prezzo attivo.
 

 quante risorse sono allocate a quel dbms in termini di RAM e processore.
 
questo lo posso verificare ma non credo siano disposti a cambiare 
hardware
 
-- 
non sono ricchione, e mi sa che non sono più comunista
 
 

 qualunque altro database engine senza particolari problemi
 
 
Pure Oracle, DB2, Sql Server? 

 come fai se non memorizzi il prezzo di ogni giorno?
 
trovi tutti i prodotti la cui max(file_date) per quel prodotto <= 
03-07-2013 è uguale a quella <= 20-09-2012.

 hardware
 
OCIO! Potrebbe anche non essere una questione hardware. Non so MySql, ma sicuramente SQL Server e - quasi - sicuramente PostgreSQL hanno la possibilità di indicare sia la quantità massima di RAM e il numero massimo di processori da impiegare.
 
-- 
Ciao!
Luca
 

 dove <data> è la data di cui vuoi sapere il prezzo attivo.
 
a parte i discorsi su pk e indici, la mia esperienza mi dice che mysql si 
siede paurosamente in caso di subquery del genere..
 
meglio una SP dove eseguo le due query separate e passo la data alla 
seconda query
 
all IMVHO
 
S.
 

 si siede paurosamente in caso di subquery del genere..
 
bah io ho avuto un problema simile usando h2 (un db scrio scrio pure java 
che gira anche in embedded mode) su diversi milioni di righe e se la cava 
almeno decentemente... penso che se ci sono gli indici giusti non c'è 
motivo di sedersi, è vero che esegue molte volte la subqery che però 
dovrebbe essere istantanea visto che rimane sempre sull'indice.

 Pure Oracle, DB2, Sql Server? 
 
nelle due righe di sopra c'era un "open source" non scritto :-)
 
 
 
-- 
zeitgeist ha uno uno stile pseudo-documentarista che va tanto di moda: 
ti copre di illazioni e sentito dire, mischia il vero col possibile e 
col falso in un unico calderone e alla fine ti porta alle conclusioni 
che vuole l'autore, cosa che va tanto di moda tra i giovini ritardati 
che si credono di sinistra di oggi.
 
 

 dove <data> è la data di cui vuoi sapere il prezzo attivo.
 
il prezzo di un singolo giorno non viene richiesto praticamente mai
 
come query di riferimento ho
 
- i prezzi in un determinato intervallo temporale (gli ultimi dieci 
giorni, dal 20-09-2012 al 10-10-2012)
- i prezzi che sono variati confrontando due date specifiche
 
in ogni caso sono ancora in fase di analisi ed ho tempi abbastanza 
ragionevoli per cui preferisco analizzare con calma la situazione e 
approfittando per approfondire le mie conoscenze in materia.
 
 
 
 
 
-- 
Che dire di a||&v| che non sia gia' stato detto della dissenteria?
 
 

 ancora tanti
 
 
Dipende anche da quante righe tira fuori per singolo supplier, se ho capito bene siamo nei paraggi di qualche milione di righe. Come verifichi i tempi? Vedi quanto ci mette a rispondere il tool con cui fare la query?

 
Hai provato ad utilizzare l'istruzione EXPLAIN  per analizzare la query
e trovare i possibili colli di bottiglia?

 ) ENGINE=InnoDB;
 
Sono l'unico che sposterebbe supplier_id e description in un'altra 
tabella collegata?
E' una cretinata?
 
  bye
	av.


No, lo farei anch'io
Duplicare la descrizione non è una bella cosa a meno che non possa 
cambiare per una nuova entry (cosa che non credo)
 
 

 Vedi quanto ci mette a rispondere il tool con cui fare la query?
 
sì, nello specifico il client a linea di comando di mysql lanciato 
sulla stessa macchina
 
è un metodo sbagliato? è poco significativo?
 
-- 
Lo stimo attratti e abbestia, solo che quando prende gli acidi scaduti, 
proprio non si sopporta.
 
 

 E' una cretinata?
 
Più che altro non ne vedo il motivo, che ci sono gli indici che sostanzialmente fanno la stessa cosa e non ti devi occupare tu della loro manutenzione.
 
-- 
Ciao!
Luca
 

 è un metodo sbagliato? è poco significativo?
 
Se ti basi sulla risposta del client, devi tener conto che un certo tempo viene impiegato per formattare a video (od in stampa, od altro) i risultati. Quindi un tempo più o meno lungo potrebbe dipendere anche dalla maggiore o minore efficienza del tool client nel fare tale formattazione. 
Per esempio io uso con Oracle un programma che di default limita le righe ritornate a 100, così da avere una risposta il più possibile rapida. Poi se scorri a video la tabella risultato ovviamente vedi il tempo reale dell'intera select. 
Certo nel tuo caso 2 secondi per tornare 330 righe con un indice dedicato ed appena creato, usando il client originale Mysql, non mi sembrano realmente una gran prestazione.
Il passo successivo potrebbe essere verificare la situazione fisica del db (tabelle più o meno disorganizzate, spazi disponibili, RAM usata, ecc.), e eventualmente il carico di rete (se stai provando da un pc diverso dal server).
Ma qui passo la palla a qualcuno esperto di Mysql dal punto sistemistico :-)
 

Il giorno venerdì 5 luglio 2013 15:39:20 UTC+2, Andrea Venturoli ha scritto:

All'incirca, dovresti quindi sostituire products.description con products.desc_id, con la seconda tabella di "decodifica" tra l'id e la descrizione.
Per evitare duplicazioni, dovresti inoltre creare un processo di scrittura che prima quarda se esiste una descrizione esattamente uguale, in tal caso ne riusa l'id, altrimenti inserisce una nuova riga descrizione con un nuovo id (trigger di inserimento ed aggiornamento su products? logica applicativa?).
Mi sembra piuttosto complicato, per risparmiare pochi GB. E su un sistema che fatica già a tirare fuori 330 righe indicizzate.

che fatica già a tirare fuori 330 righe indicizzate.
 
 
poi si scopri' che il "server" era un Pentium IV  con attaccato un disco usb 
da 4 Tera....:-)
 
ciao
fm 
 
 


Io in questo schema ci vedo un sacco di problemi, non solo quello, provo 
velocemente a elencarli:
 
- Le chiavi private devono essere opache e compatte
- Manca una chiave esterna e univoca per il prodotto
- Gli ID per collegare i record devono essere compatti e opachi
- Bisogna separare i dati stabili da quelli storici
- È essenziale mettere gli indici giusti, il che include anche l'uso degli 
indici composti!
- Per la cronaca, un buon DBMS usa l'indice per un ORDER BY + LIMIT
- È essenziale usare EXPLAIN per verificare che il query plan sia quello 
atteso
- Non si usano i floating point per memorizzare prezzi
- Si usano veri DBMS :)
 
Poi si entra nel campo delle opinioni:
 
- Io terrei il prezzo corrente nel record del prodotto così l'accesso è 
immediato.
- Creerei un'altra tabella con la storia dei prezzi, collegata a questa via 
product_id che contiene la data fino cui era valido e il prezzo.
- Ogni volta che un prodotto riceve un aggiornamento di prezzo si inserisce 
il nuovo prezzo nel record "product" e si inserisce nello storico il vecchio 
prezzo con la data odierna.
 
Ottenere uno storico è banale e rapido visto che è un index scan di piccole 
dimensioni.
 
Così facendo ridurresti drasticamente le dimensioni del database in termini 
di numero di record e spazio.
 
14 milioni di record non sono nulla di folle e un index scan di 10 record 
deve impiegare nell'ordine di grandezza del millisecondo, non dei 10 secondi 
:)


onestamente se quello è il problema e quelli sono i numeri sono 
abbastanza certo che si possa fare anche con un raspberry. posso capire 
se ci si ponesse il problema di numerosi accessi simultanei ma se siamo 
ancora a parlare di una query su una tabella non mi pare serva chissà che 
potenza di calcolo. 

 - Manca una chiave esterna e univoca per il prodotto
 
Ragionandoci, in realtà manca la chiave del fornitore! Supplier_id non è quella chiave lì, come pensavo inizialmente, bensì sembra essere la chiave del prodotto entro il fornitore. Essendo lunga 128 caratteri, probabilmente è una chiave composta da codice fornitore+ codice prodotto, tutto dentro un'unica stringona-secchione...

 ha scritto nel messaggio 
news:3eddeae6-01f0-4e79...@googlegroups.com...

... dog's penis style ...
 
90 mega  90 giga in piu' al giorno....che differenza fa?
 
Arrivera' sicuramente qualcuno a dire che si risolve tutto con il cloud 
!...:-)
 
 
ciao
fm
 
 
 
 
 

 un'unica stringona-secchione...
 
no. è solamente il codice prodotto
 
in quel database (che poi è tutto in quella tabella) non ci sono 
informazioni sui fornitori in quanto il sistema attuale gestisce un 
unico fornitore. chi ha creato questo sistema non si è neanche posto il 
problema
 
-- 
alla bambina di un anno non gliene frega un cazzo di quel che fate
la festa è solo per la vostra vanagloria di neogenitori quindi fai pure 
la solita torta all'hascish e alla bimba metti un pò di nesquik nel 
latte per festeggiare
 
 

 ha scritto nel messaggio 
news:kr79ap$6co$1...@speranza.aioe.org...

una tabella da 70 milioni di righe lunghe circa 400 bytes sono
oltre 28 GB su disco...(?)
 
Entrano anche su un disco EIDE/ATA di 15 anni fa.....
proviamo e poi  vediamo le prestazioni....
 
 
ciao
fm 
 
 


Si, voleva fare alla svelta: "Prendi i soldi e scappa".
 
... puoi aggiungere la colonna codice fornitore,
se ne hai al max 5, mi raccomando che sia di 1 (uno) carattere...:-)
 
ciao
fm 
 
 

 problema
 
Come ho detto, mi sembra un pò troppo lunga, potrebbe inficiare le prestazioni. In ogni caso se ci sono codici che usano tutti i 128 caratteri non ci si può fare molto. 
Verifica lo stato fisico della tabella, a causa dei 90.000 inserimenti giornalieri (magari in corso da anni) potrebbe essere troppo frammentata. Se in Mysql non c'è un comando apposito di riorganizzazione, non resta che un bel backup e successivo restore.

 vediamo le prestazioni....
 
certo se gli dai un server e dei dischi di ultima generazione peggio non 
va, come direbbe il fù catalano. quello che sto dicendo è che una 
operazione del genere in se non ha bisogno ne di potenza di calcolo e ne 
di chissà quali transfer rate del disco. che siano 28 giga di dati non 
glie ne può fregare di meno, io ho una libreria multimediale di un paio 
di tera gestita da un raspberry pi che fa il suo lavoro in maniera 
eccellente. certo che se uno i dati li struttura a capocchia o inserisce 
badilate di righe inutili è possibile che poi per ricercarli servano otto 
core, però qualsiasi programma di magazzino per fare la valorizzazione 
deve andare a leggere i listini ad una data e non mi pare che girino 
tutti su server di ultima generazione...
 

 03-07-2013 č uguale a quella <= 20-09-2012.
 
cioč? Non si capisce. 
 
 

 cioè? Non si capisce.
 
se registri (come è logico fare) solo le variazioni di listino di un 
prodotto puoi cercare l'ultima variazione alle due date, se corrispondono 
allora ovviamente vuol dire che fra le due date non ci sono state 
variazioni.

 
 
ah, questo vale sempre, non c'è che dire.
 
 
 
P.S.
io come db conbosco mysql, oracle e sql server, e dei tre il
paggiore mi sembra proprio mysql.
Non può essere che con sql server o oracle, pur restando il
discorso delle due tabelle, la situazione potrebbe migliorare?


c'entra poco o nulla.
In genere quando si fa una valorizzazione di magazzino non si sta col 
cronomentro
in mano a misurare i tempi (vale per il sw della Finson a 29.90 euro e per 
il SAP)
 
Invece l'OP voleva consultare le variazioni di prezzo di un singolo articolo
ed il risultato deve essere VELOCE !
 
ciao
fm
 
 
 

discorso delle due tabelle, la situazione potrebbe migliorare?
 
Per quali motivi o esperienze (mia curiosità)  dici che mysql e' il 
peggiore?
 
ciao
fm 
 
 

 
 
 
intanto per la gestione delle funzioni e delle stored procedure:
la mia esperienza mi dice che è molto più agevole gestirle
con oracle e sql server che non con mysql.
Non che con mysql non si possano fare, intendiamoci, ma imo
non c'è paragone.
E poi le funzionalità messe a disposizione, le funzioni interne,
etc., mi sembra che anche da questo punto di vista gli altri due
prodotti siano più ricchi e più vari.
 
 
 
In compenso c'è una cosa che apprezzo molto di mysql: il fatto
che quando ad esempio su un set di risultati con 1000 righe
vuoi estrarre solo le righe, diciamo da 50 a 100 lo fai senza
alcun problema, poiché il limit ti permette di specificare
l'indice di inizio di estrazione dati e quanti dati vuoi
estrarre.
Per altri prodotti riesci a specificare con facilità quanti
dati tirare fuori, ma parti sempre dall'inizio: se voglio
estrarre i primi 50 dati riesco a farlo senza problemi,
ma se voglio estrarre i dati da 50 a 100 è più complicato,
questo intendo.
Invece con mysql col limit faccio tutto agevolmente.
 
 
Questo è molto utile ad esempio per la paginazione, quando
mostri i risultati su più pagine.

 date e cost.
 
Sempre che non vari anche la descrizione. Magari non avviene da un giorno all'altro, ma dopo molti mesi potrebbe accadere.
 

 referenze ?
 
Però se usassero il "tuo" server, con 15 milioni di righe,  neppure se ne accorgerebbero di non avere la tabella superottimizzata logicamente (risposta in 0,1 ms). Che poi tale tabella di varaizioni va gestita con apposito applicativo di inserimento, mentre nell'altro modo butti dentro tutto direttamente. Pro e contro da valutare.

 Invece con mysql col limit faccio tutto agevolmente.
 
Magari perchè Mysql, furbescamente, in realtà legge tutte le prime X righe, ma semplicemente non te le restituisce. Un filtro sul modulo di output del db :-)
Solo un'ipotesi semiseria, ma in effetti è strano che altri db non diano questa possibilità.
In effetti, hai verificato se i tempi di risposta restano all'incirca uguali chiedendo N righe in posizioni diverse? Oppure si allungano in proporzione alla posizione di inizio?


Su sql dalla versione 2012 hanno aggiunto offset + fetch all'order by e fai 
quello che fai con mysql:
http://msdn.microsoft.com/en-us/library/ms188385.aspx
 
 

 referenze ?
 
In realtà, oltre alle variazioni (perchè solo il prezzo e non anche la descrizione?) c'è l'ovvio caso di articoli che, nel tempo, si aggiungono o vengono eliminati. Altra informazione che richiede un aumento di complessità applicativa.

 29.90 euro e per il SAP)
 
vero, ma se per fare il prezzo ad una data ci mette un tempo dell'ordine 
dei secondi più che il cronometro ti serve il calendario... 

 output del db :-)
 
ovviamente il costo è quello della query non limitata, se non altro 
perché se deve restituire un subset di dati ordinato l'ordinamento lo 
dovrà fare sull'intero resultset.

 14 milioni di record non sono nulla di folle
 
Concordo, anche se comincerei comunque a valutare una forma di 
partizionamento dei dati (molto dipende dal DBMS che si utilizza)
 
Enrico

 Sempre che non vari anche la descrizione. Magari non avviene da un giorno all'altro, ma dopo molti mesi potrebbe accadere.
 
Avevo pensato alla stessa cosa ma, a guardare la tabella iniziale, sembra non succedere. Intendo: non c'è un codice articolo e una descrizione, c'è solo un campo descrizione, il che mi fa pensare che nel tempo non cambi; non ne conosciamo il contenuto: potrebbe essere anche un codice derivato da bar code...
 
-- 
Ciao!
Luca

 In realtà, oltre alle variazioni (perchè solo il prezzo e non anche la descrizione?) c'è l'ovvio caso di articoli che, nel tempo, si aggiungono o vengono eliminati. Altra informazione che richiede un aumento di complessità applicativa.
 
Vero. In effetti bisogna lavorare di bilancia: su un piatto butti la complessità applicativa, sull'altro la quantità di dati da trattare, e vedi che ne viene fuori.
 
-- 
Ciao!
Luca


Poi di solito la complessità applicativa ha un costo maggiore della complessità hardware (cioè: paghi di più per lo sviluppo software che per l'uso più intenso od il potenziamento dell'hardware). Detto questo, la soluzione "banale" attuale potrebbe non essere la peggiore. Magari spendono qualche centone per hardware un poco migliore, ed hanno risolto. Lavoro di meno per gli sviluppatori, certo :-)

 dovrà fare sull'intero resultset.
 
E se non deve fare nessun ordinamento speciale, solo l'ordine di un indice? Chiedo, perchè non ho mai usato Mysql.
 

 semplice, visto che un VARCHAR(128) non e` una chiave per definizione
 
Oh bella, e questa affermazione così perentoria da dove arriva?
 
-- 
Ciao!
Luca
 

 Oh bella, e questa affermazione così perentoria da dove arriva?
 
Guarda personalmente sottoscrivo questo: 
http://www.soft-land.org/documenti/pk
 
 
Ciao
  Francesco


 
Sono l'unico a pensare che un varchar(128) come chiave primaria sia un obrobrio?
Da come lavori la query quasi sicuramente viene fato un full table scan, quello
associato al varchar e alla mancanza di indici appropriati e' la prima causa
della lentezza, crea un vero id prodotto (intero o char fa poca differenza ma
non varchar) io ho tabelle prodotto con il codice char di 15 o 20 caratteri,
tabelle con svariati milioni di record, ma tempi assolutamente congrui, poi
oltre un certo limite l'ottimizzazione non puo' che essere hw quindi o si rimane
su MySql cambiando server (o rivedendone la cofigurazione per memoria allocabile
e potenza cpu assegnata) o si cambia MySql proprio. 

 Guarda personalmente sottoscrivo questo: 
http://www.soft-land.org/documenti/pk
 
 
Lo conosco da molto tempo. E' un po' la diatriba tra chi è purista della teoria relazionale, e chi pensa che una specie di indice come chiave primaria sia sempre un bene. Personalmente io sto dalla parte del buon Davide: in medio stat virtus! Ci sono situazioni in cui è sensato usare indici come chiavi primarie (a proposito, io impiego dei GUID), altre in cui è opportuno impiegare uno o più campi che, si sa in partenza, non verranno modificati nel tempo. 
 
NOTA. Volendo entrare nel merito, proprio per come è costruito, il varchar non è il massimo dal punto di vista prestazionale; tuttavia - prove svolte su PostgreSql e su SQLServer - non c'è poi questa grande differenza, almeno su 6 milioni di record circa.
 
-- 
Ciao!
Luca

Il giorno lunedì 8 luglio 2013 10:59:45 UTC+2, > > NOTA. Volendo entrare nel merito, proprio per come è costruito, il varchar non è il massimo dal punto di vista prestazionale; tuttavia - prove svolte su PostgreSql e su SQLServer - non c'è poi questa grande differenza, almeno su 6 milioni di record circa.
 
Penso che dipenda anche molto dal grado di riempimento del campo. Un codice fiscale definito Varchar che è sempre di 16 caratteri non degrada le prestazioni come un varchar di 128 riempito solo parzialmente. Forse perchè l'albero binario dell'indice, o struttura analoga,  è molto più complesso?

NOTA. Volendo entrare nel merito, proprio per come è costruito, il varchar non è il massimo dal punto di vista prestazionale; 
 
Appunto. poi occorre distinguere se la tabella ha pochi a trillairdi di record,
indici strutturati ecc ecc. Dopo 20 anni che lavoro con i db solo una cosa ho
imparato: che non esiste una soluzione miracolosa che abbatte i tempi o i
problemmi da 100 a zero in pochi passi, e' tutto un limare a destra e a manca...
 
Nel merito io pure in certe situazioni ha chiavi char(15) o Char(20) che non
danno problemi di sorta, un varchar(128) dimostra un certo grado di
incoscenza...

 incoscenza...
 
scusa l'ignoranza, ma in che senso? qual'è il problema degli indici di varchar?
 

Stavamo scarsi a Cretinetty, mancava solo Luca Menegotto con l'idea:

il campo `supplier_id` non contiene, come si potrebbe *ingenuamente* 
pensare, l'id del fornitore ma il codice che il fornitore assegna al 
prodotto
 
che io capisco fare le cose di fretta, capisco tutto ma almeno i nomi 
dei campi si possono mettere con un minimo di buon senso ...
 
-- 
avevo la foto di una palla da neve che avevo cominciato a far rotolare
all'inizio della camminata di ritorno verso le macchine. all'arrivo al
posteggio la palla da neve era piu' grossa di tafano e piu' alta di
fabmind.
 
 

"rootkit" ha scritto nel messaggio 
news:42059c52-8e43-49cf...@googlegroups.com...

Parlava di chiavi, non di "semplici" indici.
E se magari la chiave è pure clustered hai tutti gli altri indici pesanti di 
conseguenza.
 

 pesanti di conseguenza.
 
cambio la domanda: qual'è il problema delle chiavi varchar (rispetto ai 
char, a questo punto)?

 dovrebbe essere istantanea visto che rimane sempre sull'indice.
 
Vero, ma e` vero anche che con MySQL tutto e` possibile :)
Per dire, nella query da te postata, MySQL fa prima un index scan per la 
parte in subquery e poi un full scan per il resto. Diversamente, PostgreSQL 
fa sempre un index scan, sia per la parte in subquery, sia per la parte 
esterna
 
Enrico

 char, a questo punto)?
 
in Sql server vengono usati 2 byte in piu'...ovvero "pesano" di piu'...
 
Non so se lo stesso succede in MySql ...
 
ciao
fm 
 
 

char, a questo punto)?
 
sono piu' pesanti, db2 e sqlserver (ma credo anche Oracle) aggiungono due byte,
uno crede di risparmiare invece aumenta il peso del proprio db, su db2 (il
sistema che conosco meglio) l'allocazione dello storage di sistema e' data dalla
lunghezza massima del campo (128 in questo caso) + due byte.
Il motore sql che procede all'ordinamento "fatica" di piu' (dacche' e' cosa
buona avere almeno un index sul campo chiave).
Se per sbaglio fai una query che comporta un full table scan allora ti diverti
proprio :-) 
VarChar mi hanno insegnato all'epoca va usato com molto discernimento, per campi
descrittivi e proprio quando non se ne puo' fare a meno (lo standard ai bei
tempi era che le descrizioni brevi fossere Char(25) quelle lunghe Char(35)).
E' vero che la potenza hardware compensa e maschera la situazione, ma al
crescere del numero di record (qualche milione come nell'esempio dell'op) il db
va in panne ugualmente.

 esterna
 
In Oracle "comanda" l'ottimizzatore (che non è un burocrate, ma un modulo interno :-), decide lui se usare o no un indice in base ai parametri di costo. Di default il tempo di risposta non è il parametro principale (si valutano occupazione di memoria, traffico sulla rete, frammentazione dello spazio fisico, ed altro). Per forzare l'uso di un indice bisogna scrivere la select con speciali parametri (hints).
Può essere che Mysql operi allo stesso modo. 

 >cambio la domanda: qual'ï¿½ il problema delle chiavi varchar (rispetto ai 

Se aggiunge solo 2 bytes su 128 non mi sembra ci sia uno "scoppio" dello spazio necessario, e relativa potenza di calcolo. Vedo più il problema nel caso in cui l'occupazione dei 128 bytes sia effettivamente molto variabile, a quel punto il db è costretto ad allocare e gestire spazi ugualmente variabili con quel che consegue. 

 Vedo piů il problema nel caso in cui l'occupazione dei 128 bytes sia effettivamente molto variabile, a quel punto il db č costretto ad allocare e gestire spazi ugualmente variabili con quel che consegue. 
 
il punto e' questo, se i 128 fossero sempre pieni, paradossalmente il motore db
faticherebbe molto di meno


Dipende, metti che la maggior parte dei dati sono grandi attorno alla metà 
del valore massimo, hai meno attività di i/o usando un varchar() piuttusto 
che un char().
 


Se sul serio i dati sono variabili fino a 128 bytes massimi e nel concreto 
la variabilità esiste davvero e non è solo sulla carta, il numero di pagine 
che l'engine si deve tirar su per accedere ai dati è inferiore nel caso di 
utilizzo di varchar piuttosto che char, ergo l'engine è ben felice di 
risparmiare spazio nella sua prezioa cache dove tiene i dati a cui accede 
per risolvere le query.
 

 su un campo varchar(128) una cagata pazzesca.
 
Pero' non e' chiaro quali siano secondo te i motivi per considerarla cosi',
visto che i motivi addotti da altri non sembrano convincerti.
 
Ciao,
Marco.
 
-- 
 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it
 
 
 

 visto che i motivi addotti da altri non sembrano convincerti.
 
 
Ho letto il thread tutto d'un fiato oggi perché questo tipo di problemi 
di ottimizzazione mi sono sempre interessati (anche se poi magari non ne 
ho le competenze).
 
Se avessi il compito di riprogettare il db e la possibilità contestuale 
di rivedere l'applicazione procederei nel mettere in pratica diversi 
test, uno dei quali è quello di sostituire la chiave varchar in un id 
numerico.
 
L'uso di un id numerico permette al db di:
- eventualmente ottimizzare l'accesso all'indice in quanto tutte le 
chiavi hanno la stessa lunghezza
- inserire più chiavi in ogni blocco dell'indice (considerando un indice 
btree*) quindi la possibilità di dover accedere ad un numero inferiore 
di pagine
- più veloce comparazione fra i valori degli indici perché non si 
arriverà mai a 128 bytes ma al massimo 8 per un intero veramente grande...
 
Se poi si procedesse con una normalizzazione più spinta, con i varchar 
inseriti in un'altra tabella, ti ritroveresti una tabella con lunghezza 
record fissa a circa 40 caratteri, ovvero 560 MB... con il vantaggio che 
magari se lo tiene in memoria il file...
 
 
Io partirei dalla fine, definendo i seguenti parametri:
- quali sono le query che si vogliono far girare più spesso oppure
- entro quali tempi devono fornire una risposta (2 secondi possono 
essere accettabili per una risposta interattiva ma se devo fare la 
stessa ricerca in batch su 10.000 codici mi diventa impossibile....)
- su quale hardware devo far girare il tutto ovvero quanti fondi sono 
stanziati per un hardware più veloce....
 
 
poi viene tutto il resto....

 sono 330?
 
Gentilmente mi potresti dire quali sono gli indici attivi al momento 
della EXPLAIN ?
 
Esiste un indice composto supplier_id, file_date ? Se non esiste 
potresti crearlo e ripetere la EXPLAIN ?
 

 EXPLAIN ?
 
(supplier_id, file_date) e supplier_id
 
 
 
 
 
-- 
è la visione hopperiana di una transumansa quotidiana di sentimenti
digitali che altrimenti potremmo definire fottesega
 
 

 stanziati per un hardware più veloce....
 
e la risposta è (rullo di tamburi) "possiamo mettere un po' di ram in 
più"
 
-- 
Nel '94 votai Berlusconi perchè mi feci imbambolare dalla discesa in
campo.
Ero davvero convinto che sarebbe tutto cambiato rispetto agli anni di
Andreotti/Craxi
(Soprano, IAT, 26/03/2010
 
 

 (supplier_id, file_date) e supplier_id
 
scusa se insisto ma chiedo conferma visto che nel messaggio originale 
dicevi:
  PRIMARY KEY (`file_date`,`supplier_id`) e non supplier_id, file_date
 
Hai la possibilità di modificare il software che fa le query ? Perché 
magari potresti spezzare la query in più parti ottimizzandole 
separatamente ?
Ad esempio potresti fare una prima query per prendere le prime 10 date 
(o la min(file_date) fra queste 10) e poi fare la select chiedendo quel 
codice prototto AND che la data sia fra quelle indicate (o >= la data 
trovata). Dovresti in questo modo poter sfruttare appieno gli indici e 
poi il sort avviene su 10 record e non su 330.
 
Il secondo esperimento è magari quello di provare a usare codici ID 
numerici al posto di varchar(128) come chiavi e indici per le 
ottimizzazioni di cui si parlava prima.
 
Immagino poi che non sia possibile avere il file, nemmeno in formato 
anonimizzato (importi a 0, descrizioni a "Prodotto X", codici a 
"CODXXXXXXX", ovviamente con lo stesso codice reale abbinato allo stesso 
CODXXXXXXX così che si possa ripetere la stessa query della EXPLAIN...)
 
 
 
 
 

 e la risposta è (rullo di tamburi) "possiamo mettere un po' di ram in più"
 
 
Sai, se il server ora ha 256 mega di ram ben venga l'espansione... se ne 
ha 16 GB... non mi sembra di aver letto nulla sulla configurazione hw/sw 
su cui gira il server, se è un db server dedicato o il pc della 
segretaria...
 
E già hanno chiesto di verificare la configurazione di mysql...
 
io penserei anche a passare da innodb a qualche altro metodo di storage 
più veloce...
 
 

 veloce...
 
pensavo di sostituire mysql con postgresql (non vogliono spendere in 
hardware figuriamoci in software)
 
sul confronto tra i due ho sempre letto articoli che avevano un 
retrogusto di "fan boy" se hai qualche articolo da suggerirmi lo 
leggerei con piacere
 
fermo restando che che "butterò" la tabella esistente e creerò uno 
schema più ragionato.
 
-- 
non ci si puo' leticare con brancaleone.
e' come prendersela con un handicappato.
 
 


Parlavo della differenza in generale tra i varchar() e i char() a livello di 
occupazione, ma questo non vuole dire che un varchar(128)  anche con dati 
che internamente sono davvero variabili essendo meglio da un punto di vista 
di occupazione di spazio e quindi attività di lettura/scrittura di pagine di 
dati rispetto ad un char(128) sia una buona scelta come chiave primaria... 
visto che le pk spesso sono usate come chiavi esterne in altre tabelle hai 
qui si molto overhead in più per far gestire l'integrità dei dati 
direttamente al motore tramite DRI. E come accennavo, visto che di default è 
così, se la pk sotto è anche un indice clustered, hai anche tutti gli altri 
indici di quella tabella che occupato molto spazio visto che hanno in pancia 
le chiavi dell'indice clustered che appunto servono per referenziare le 
singole righe della tabella, e il tutto si traduce ancora alla fine in molta 
attività di i/o per il motore.
 


 
Eh, ci vorrebbe nostradamus per sapere a priori quali sono le query che 
girano più spesso... :-)
Infatti di solito si fa alla rovescia, nel senso che con ambiente in uso 
reale si monitorano le query utilizzate per sapere dove ha più senso 
intervenire, visto che potrebbe capitare di dover metter mano a una query 
che gira in 100 ms ma che viene chiamata una milionata di volte al giorno 
piuttosto che dedicare tempo ad una query che gira in 2 minuti ma che viene 
usata 10 volte nella giornata.
 

 schema più ragionato.
 
 
Questa è la prima prova che devi fare. La macchina sembra ok, per quello 
che devi fare. Dovresti portare la tabella nettamente sotto il giga, 
almeno la parte indici, così che non debba leggere le pagine dal disco !
 
Ti invito anche a leggere questo articolo che fornisce degli hint 
interessanti e dei suggeriemnti per prove da effettuare, nonché degli 
spunti per approfondimenti.
 
 

 stanziati per un hardware più veloce....
 
In verità, quando si analizzano i dati, queste domande non sono la fine, ma sono l'inizio... :-)
In genere, poi, si dovrebbe prima fare un'analisi della pura struttura logica, eventualmente normalizzata al massimo grado. Successivamente fare una progettazione legata ai vincoli hardware, linguaggio, dbms, ecc.  

 
http://msdn.microsoft.com/en-us/library/ms188385.aspx
 
 
Ohssantamaria.... spero di non aver capito la ratio di quel coso... ma l'uso 
dell'indice per ottenere un subset ordinato e limitato senza un full-scan è 
compito del *planner* non del linguaggio....