Newsgroup: it.comp.www.php
Titolo: Indice auto_increment e "buchi"

salve, ho iniziato da poco la mia avventura con PHP / MySQL e già più di una 
volta mi sono imbattuto in un problema: quando creo una tabella per 
archiviare testi (news o piccoli messaggi) mi resta sempre comodo usare un 
id e, per evitare di doverlo calcolare ogni volta lo setto su 
auto_increment. il problema viene fuori quando cancello dei dati già 
inseriti, naturalmente l'indice non se ne preoccupa e continua ad 
autoincrementarsi, lasciando così posizioni vuote, complicandomi la vita 
(diventa troppo grande e non mi permette di usare funzioni tipo random)...
volevo chiedervi conoscete un semplice modo per ovviare a questo problema? 
esiste qualcosa del genere: inserisci questo testo e prendi come id la prima 
posizione disponibile? oppure va gestito tramite script? a tentativi?
grazie!
carlo

(diventa troppo grande e non mi permette di usare funzioni tipo random)...
La questione è stata dibattuta parecchio. Prova a cercare con Google,
anche su it.comp.software.database e free.it.comp.database.mysql .
Comunque in sostanza il comportamento è corretto, il problema è che
l'auto-increment è alla fine solo un generatore di valori univoci, non
un numeratore.
Puoi ovviare in parte alla cosa ottimizzando periodicamente la
tabella, ma credo che ti consenta di resettare il numeratore al valore
più alto, non di colmare i buchi all'interno della sequenza.
Matteo
------------------------------------------
Un po' di là dal mare c'è una terra chiara
che di confini e argini non sa
------------------------------------------



Ciao Giacomo,
invece di rendere l'id autoincrementante, prima di fare la insert
fai una select max(id) from tabella e ti ricavi l'ultimo id, aggiungi
1 e il problema è risolto ;)
ciaux Daniel
http://www.gizax.it

 anche su it.comp.software.database e free.it.comp.database.mysql .
ho provato, ma sono un po' in difficoltà le parole chiave da usare per la 
ricerca, visto che hai già visto queste discussioni sai darmi un 
suggerimento?
nel frattempo avevo scritto questa:
function trovaid($nometabella, $db){
$indici = mysql_query("SELECT id FROM $nometabella ORDER BY id", $db) or die 
("Errore nella selezione dell'id.");
$i = 1;
while ($line = mysql_fetch_row($indici)) {
if ($line[0] != $i) return $i;
else $i++;
}
return $i;
}
si può fare in maniera più veloce? accetto volentieri consigli/suggerimenti 
per migliorarla!

 "buco" rimane...
io intendevo dalla prossima volta invece di mettere campo autoincrement
usa il metodo che ti ho detto. select max(id) ti restituisce l'elemento id
piu grande, aggiungi a questo uno e avrai sempre e solo l'elemento seguente
senza mai perdere numeri per strada anche dovuto a cancellazioni
ciao

 (diventa troppo grande e non mi permette di usare funzioni tipo random)...
Che diventi troppo grande non ha molto senso. Se non sbaglio puoi metterlo
a 64 bit (dipende dal DB. Uso poco MySQL), e anche inserendo 10 valori al
secondo non ti basta la vita dell'Universo per riempirlo. Forse con
qualche milione di insert/secondo ce la fai... :)
Per il random, basta usare
select * from tabella order by rand() limit 1
o simile.
Bye.

 senza mai perdere numeri per strada anche dovuto a cancellazioni
Bell'idea ...
Che non perdi niente per strada č vero, ma ho qualche dubbio sulla
consistenza dei dati.
E forse *piů* di qualche dubbio ... ;-)
ciao!
--ev

 E forse *piů* di qualche dubbio ... ;-)
se ti spieghi magari riusciamo a capire

 se ti spieghi magari riusciamo a capire
Pippo "chiede" il massimo id della tabella. il sistema gli restituisce,
ad esempio, 10.
Fatto sta che anche Pluto ha fatto la stessa cosa, con lo stesso
risultato (supponendo che passi un attimo di tempo fra la richiesta e
l'insert).
Risultato: entrambi inseriscono qualcosa che ha id 10, con il casino che
ne consegue.
Se la cosa ti sembra "strana", prova a pensare ad un forum popolato da
centinaia di utenti che scrivono articoli, commenti e via dicendo.
(mi scuso se l'esempio č fatto male ma sono di corsa, casomai dopo
spiego con piů calma!)
Ciao!
--ev

 ne consegue.
E, a parte questo, inserisci gli id da 1 a 10, cancelli il 3, max() ti
torna 10 e tu inserisci l'11.
L'unico modo e` uno scan degli id della tabella per trovare i buchi e
prendere il piu` basso.
Il metodo del max funziona solo se e` uno "stack": ne inserisci 10, togli
l'ultimo e il penultimo, ne inserisci un altro, ecc.
Bye.

 senza mai perdere numeri per strada anche dovuto a cancellazioni
E se vengono fatte 2 richieste contemporanee?
Ciao
Marco

 Bye.
No forse non mi sono spiegato. Questa è una cosa che si può fare solo in
fase di partenza del progetto. E' chiaro che ora è inutile avendo un db già
pieno. Ma se tu calcoli dalla partenza del servizio avrai la possibilità di
prendere l'elemento piu alto e aggiungere uno senza avere problemi in fase
di cancellazione. L'unico problema possibile è la gestione delle
connessioni contemporanee che come diceva giustamente Marco qui può
diventare un problema e a cui sinceramente non avevo pensato.
chissa se mi sono capito.

 torna 10 e tu inserisci l'11.
alessandro ha preso in pieno il problema...!
continuo a non capire la tua soluzione daniel, mi appare come un 
auto_increment "manuale", solo con qualche problema in più (vedi le 
connessioni contemporanee) 

 a 64 bit (dipende dal DB...
...forse la mia è una mania, ma cercavo di limitare gli sprechi di spazio il 
più possibile a favore della chiarezza e della velocità (credo)

 disponibile? oppure va gestito tramite script? a tentativi?
Attraverso script è sicuramente possibile modificare quel
comportamento, ma mi sento di sconsigliartelo.
Il tuo problema è da qualche altra parte e probabilmente si
può risolvere mantenendo la chiave primaria autoincrementale.
Ciao.
-- 
Federico R.

di cancellazione. 
Restano i buchi, come dice Alessandro. Non risolvi il problema e vai
solo in cerca di guai, IMHO.
L'auto_increment serve sostanzialmente a trovare valori univoci da
utilizzare come chiavi primarie artificiali (ovvero non naturali, come
potrebbe essere il barcode, il codice fiscale o altro). Non va usato
né come numeratore né preoccupandosi di buchi o sequenze, serve a
identificare univocamente un record.
Ma perché, Daniel, dici di avere problemi con random? Nel senso che
potrebbe restituirti un valore non presente nella tabella? Se devi
estrarre uno o più record random, potresti risolvere con la funzione
rand() di MySQL, invece di passare per PHP.
Ciao


allora,
grazie alle chiacchiere lette/fatte qui e su altri forum (per chi è 
interessato questi in particolare... 
http://forum.html.it/forum/showthread.php?s=8e4f2a02ba86579ee473b2a8ac0c7279&postid=6990055e
 
http://forum.html.it/forum/showthread.php?s=8e4f2a02ba86579ee473b2a8ac0c7279&threadid=747272
 ) 
sono arrivato alla conclusione che avere gli id numerati per benino come 
voglio io abbia un vantaggio puramente estetico e portino a non pochi 
"effetti collaterali" (ho scoperto l'acqua calda, insomma).
quello che voglio chiedervi ora è:
quanto influisce la dimensione del campo id sulla velocità/efficenza delle 
query??? voi quanto lo settate grande?
in conclusione mi rendo conto che la parte più difficile sia mettere da 
parte la mia 'pignoleria' a discapito di una funzionalità maggiore. alla 
fine non sto facendo un database per la nasa e mi sa proprio che imposterò 
l'id a INT(10) UNSIGNED e a quanto ho capito la differenza di velocità non 
dovrebbe essere rilevante. voi che dite? 

 query??? voi quanto lo settate grande?
Nulla. A meno che non lo imposti come testo.
Se e` numerico, sara` leggerissimissimissimamente piu` veloce se usi le
stesse dimensioni di parola della CPU (x86-> 32 bit, amd64->64bit, ecc.)
 
Bye.

Giacomo wrote:

ora basta con queste connessioni contemporanee..
hai mai sentito parlare di transazioni?
e cmq se qualcuno vuole può tranquillamente gestire l'autoincrement da solo
naturalmente con scapito di velocità, memoria..
basta aggiungere un campo per mantenere le relazioni tra valori conseguenti
e modificare eliminare solo i valori di tale campo..
-- 
www.iuz-lab.info

 eliminare solo i valori di tale campo..
Tutto si puo` fare, anche implementare l'integrita` referenziale a mano e
simulare le transazioni tramite lock ma, come giustamente dici, a scapito
di velocita`, memoria e, aggiungo io, mal di testa. :)
Bye.