Newsgroup: it.comp.software.database
Titolo: [CURIOSITA'] DELETE "pesante"

Ciao a tutti!
Vi chiedo un po' di cose che mi sono saltate in mente oggi, per pura
curiosità!
I fatti sono questi:
ho un db Postgres con una tabella principale che contiene circa 5000
record. A questa tabella, sono collegate tramite PK/FK altre 6 tabelle,
ognuna delle quali contiene 10-12 record per ognuno dei 5000 record della
tabella principale. Queste 6 tabelle hanno una PK, una FK composta ed un
indice, composto anch'esso da due campi, che uso per le ricerche. Le 6
tabelle collegate hanno una relazione "ON DELETE CASCADE".
Oggi, ho laciato una query del tipo:
DELETE FROM tabella_principale where CONDIZIONE
dove con "CONDIZIONE" vengono match-ati circa 1500 record.
Il DELETE ci ha messo circa 8 minuti per terminare (pentium 4 1500, 512 
RAM e disco SCSI): non che la cosa mi spaventi, al contrario mi sono
nate delle curiosità:
- se io avessi fatto 6 DELETE singoli sulle 6 tabelle collegate e _poi_
avessi lanciato il DELETE sulla principale, sarebbe cambiato qualcosa in
termini di tempi? 
- cancellare gli indici, lanciare il delete e ricreare gli indici
sarebbe servito a qualcosa o, ancora, sarebbe stato uno spreco di tempo
e di cicli di clock?
Poi, un'altra cosetta!
Dopo il DELETE, ho lanciato un VACUUM sul db.
Da buon cusioso, tenevo d'occhio lo spazio su disco occupato dal DB prima
e dopo il DELETE. I dati sono (i numeri sono solo riferimenti e, fra
l'altro, li misuravo in MB, quindi ci potrebbe essere qualche scarto a
livello di K! Contate poi che il DB non è immenso e pesa sui 25 mega):
 
prima del DELETE, il DB pesa 25 
dopo il DELETE, il DB pesa ancora 25 
dopo il VACUUM, il db pesa circa 21 
 
Questo mi ha portato a fare una considerazione ... Giusta o sbagliata
non so, chiedo a voi! 
 
Il DELETE non cancella fisicamente le righe, solamente ne azzera il
contenuto o le undef-inisce tenendosele buone per successivi insert.
Una volta lanciato un VACUUM, invece, le righe vengono fisicamente
eliminate. 
 
Ci sono andato vicino o ho cannato di brutto? :-)
Grazie a chiunque mi voglia "delucidare" e scusate eventuali
"strafalcioni tecnico-linguistici"! (ben accette correzioni anche in
tal senso!)
--ev

 Il DELETE non cancella fisicamente le righe
Nessun database che si rispetti perde tempo a *cancellare* realmente
i dati, si limita a marcare lo spazio come "libero".
Davide

 i dati, si limita a marcare lo spazio come "libero".
Questo non lo sapevo! :-)
Funziona allo stesso modo (anche se in ambiti differenti e con modalità
differenti) della cancellazione di un file su filesystem, giusto? Il
contenuto resta "scritto" ma se ne perdono i "confini", quindi lo spazio
risulta utilizzabile.
Ma in pratica, allora, il VACUUM esegue realmente la cancellazione?
Ciao e grazie ancora!
--ev

 Ma in pratica, allora, il VACUUM esegue realmente la cancellazione?
Esatto. Come da documentazione
VACUUM reclaims storage occupied by deleted tuples
Davide

 VACUUM reclaims storage occupied by deleted tuples
Azz, mi cospargo il capo di cenere ...
VACUUM reclaims storage occupied by deleted tuples. In normal
PostgreSQL operation, tuples that are DELETEd or obsoleted by UPDATE
are not physically removed from their table; they remain present until
a VACUUM is done. Therefore it's necessary to do VACUUM  periodically,
especially on frequently-updated tables. 
C'era, bastava leggere ... Mi sa che è meglio se mi faccio una
rinfrescatina della documentazione! :-\
Chiedo venia!
--ev

 
Non sono proprio daccordo con questa affermazione.
Di fatto, l'albero degli indici, mantiene un puntatore alla
 tabella a cui riferiscono le righe.
Se cancelli le righe (con delete), i puntatori devono essere
 modificati. Non solo.
Poiché gli indici sono costruiti con strutture ad albero
 bilanciato, per ogni cancellazione di una riga, l'rdbms
 deve verificare che l'albero resti bilanciato.
 Il lavoro che deve fare nel caso in cui si sbilanci è:
  * fare lo split di un nodo per generarne due, nel caso
	di inserimenti
  * fondere due nodi, nel caso di cancellazioni

Quello che intendevo dire e': rimuovere gli indici, fare la delete
e ricostruire gli indici, forse ci mette lo stesso che fare la
delete *senza* rimuovere gli indici.
Davide