Zunächst lege ich eine harmlose Tabelle an:
SQL> r 1 create table t1 2 as 3 select rownum col1 4 from dual 5* connect by level <= 100000 Tabelle wurde erstellt.
Tom Kytes ShowSpace-Prozedur liefert dafür folgende Angaben:
SQL> exec show_space('T1')
Unformatted Blocks ..................... 0
FS1 Blocks (0-25) ..................... 0
FS2 Blocks (25-50) ..................... 0
FS3 Blocks (50-75) ..................... 0
FS4 Blocks (75-100)..................... 0
Full Blocks ..................... 76
Total Blocks............................ 128
Total Bytes............................. 2,097,152
Total MBytes............................ 2
Unused Blocks........................... 45
Unused Bytes............................ 737,280
Last Used Ext FileId.................... 4
Last Used Ext BlockId................... 709
Last Used Block......................... 19
PL/SQL-Prozedur erfolgreich abgeschlossen.
Anschließend komprimiere ich die Tabelle mit Hilfe des SHRINK SPACE Kommandos:
SQL> alter table t1 enable row movement; Tabelle wurde geändert. SQL> alter table t1 shrink space; Tabelle wurde geändert.
Und erhalte folgende Statistiken:
SQL> exec show_space('T1')
Unformatted Blocks ..................... 0
FS1 Blocks (0-25) ..................... 0
FS2 Blocks (25-50) ..................... 0
FS3 Blocks (50-75) ..................... 0
FS4 Blocks (75-100)..................... 0
Full Blocks ..................... 76
Total Blocks............................ 84
Total Bytes............................. 1,376,256
Total MBytes............................ 1
Unused Blocks........................... 1
Unused Bytes............................ 16,384
Last Used Ext FileId.................... 4
Last Used Ext BlockId................... 709
Last Used Block......................... 19
PL/SQL-Prozedur erfolgreich abgeschlossen.
Die nicht verwendeten Blocks werden also freigegeben, statt 128 Blocks werden nur noch 84 Blocks verwendet. An den gefüllten Blocks ändert sich nichts.
Im nächsten Schritt lösche ich 80% der Zeilen aus der Tabelle.
SQL> delete from t1 where col1 <= 80000; 80000 Zeilen wurden gelöscht. SQL> commit; Transaktion mit COMMIT abgeschlossen.
An der Anzahl der verwendeten Blocks ändert sich dadurch nichts, durchaus aber am Füllgrad der Blocks
SQL> exec show_space('T1')
Unformatted Blocks ..................... 0
FS1 Blocks (0-25) ..................... 0
FS2 Blocks (25-50) ..................... 1
FS3 Blocks (50-75) ..................... 0
FS4 Blocks (75-100)..................... 60
Full Blocks ..................... 15
Total Blocks............................ 84
Total Bytes............................. 1,376,256
Total MBytes............................ 1
Unused Blocks........................... 1
Unused Bytes............................ 16,384
Last Used Ext FileId.................... 4
Last Used Ext BlockId................... 709
Last Used Block......................... 19
PL/SQL-Prozedur erfolgreich abgeschlossen.
Ein anschließendes SHRINK für die Tabelle führt dann zum Reorg und zu einer Verkleinerung der Tabelle:
SQL> alter table t1 shrink space;
Tabelle wurde geändert.
Abgelaufen: 00:00:05.62
SQL> exec show_space('T1')
Unformatted Blocks ..................... 0
FS1 Blocks (0-25) ..................... 0
FS2 Blocks (25-50) ..................... 0
FS3 Blocks (50-75) ..................... 0
FS4 Blocks (75-100)..................... 1
Full Blocks ..................... 15
Total Blocks............................ 20
Total Bytes............................. 327,680
Total MBytes............................ 0
Unused Blocks........................... 0
Unused Bytes............................ 0
Last Used Ext FileId.................... 4
Last Used Ext BlockId................... 573
Last Used Block......................... 4
PL/SQL-Prozedur erfolgreich abgeschlossen.
Deutlich wird auch, dass die physikalische Reorganisation Ressourcen kostet - im harmlosen Beispielfall immerhin bereits mehr als fünf Sekunden.
Ein hübsches Hilfsmittel für die Analyse ist auch das dbms_rowid-Package, mit dem man die Zuordnung der Sätze zu den Blocks detailliert bestimmen kann:
SQL> r
1 select blockid, count(*)
2 from (select dbms_rowid.rowid_block_number(rowid) blockid
3 from t1)
4 group by blockid
5* order by blockid
BLOCKID COUNT(*)
---------- ----------
560 1328
561 1328
562 1328
563 1328
564 1328
565 1328
566 1328
567 1328
568 1328
569 1328
570 1328
571 1328
572 1328
574 1328
575 1328
576 80
16 Zeilen ausgewählt.
Keine Kommentare:
Kommentar veröffentlichen