-- Blockgröße 16 K
SQL> sho parameter db_block_size
NAME TYPE VALUE
------------------------------------ ----------- -----
db_block_size integer 16384
-- Anlage einer Testtabelle
SQL> create table t1
2 as
3 select rownum col1
4 from dual
5 connect by level < 10000;
Tabelle wurde erstellt.
SQL> r
1 select blockid
2 , count(*)
3 , sum(colsize)
4 from (select dbms_rowid.rowid_block_number(rowid) blockid
5 , vsize(col1) colsize
6 from t1)
7 group by blockid
8* order by blockid
BLOCKID COUNT(*) SUM(COLSIZE)
---------- ---------- ------------
224 1327 3869
225 1327 3968
226 1327 3968
227 1327 3967
228 1327 3968
229 1327 3968
230 1327 3968
231 710 2123
8 Zeilen ausgewählt.
Die komplett gefüllten Blocks enthalten also jeweils 1327 Sätze, aber die Nettodaten der einzigen Tabellenspalte umfassen jeweils nur ca. 4K - also nur ein Viertel der Blocksize!
Eine Änderung der PCTFREE-Einstellung von 10 auf 0 verändert das Ergebnis im erwarteten Umfang von ~ 10%:
SQL> r
1 select blockid
2 , count(*)
3 , sum(colsize)
4 from (select dbms_rowid.rowid_block_number(rowid) blockid
5 , vsize(col2) colsize
6 from t2)
7 group by blockid
8* order by blockid
BLOCKID COUNT(*) SUM(COLSIZE)
---------- ---------- ------------
236 1475 4312
237 1475 4410
238 1475 4410
239 1475 4410
240 1475 4411
241 1475 4410
242 1149 3436
7 Zeilen ausgewählt.
Man kann sich den Inhalt eines Blocks ansehen, indem man einen Blockdump erstellt:
SQL> alter system dump datafile 4 block 224; System wurde geändert.
Der Dump wird im user_dump_dest abgelegt und enthält diverse Repräsentationen der Blockinhalte, darunter eine hexadezimale Darstellung, in der man die Datenverteilung relativ gut erkennen kann. Dort sieht man im gegebenen Fall auch relativ große Lücken, die ich mir aktuell noch nicht erklären kann.
Deshalb noch ein dritter Versuch mit String-Werten fester Breite:
SQL> r
1 create table t3
2 as
3 select 'AAAAAAAA' col3
4 from dual
5* connect by level < 10000
Tabelle wurde erstellt.
SQL> r
1 select blockid
2 , count(*)
3 , sum(colsize)
4 from (select dbms_rowid.rowid_block_number(rowid) blockid
5 , vsize(col3) colsize
6 from t3)
7 group by blockid
8* order by blockid
BLOCKID COUNT(*) SUM(COLSIZE)
---------- ---------- ------------
248 1043 8344
249 1043 8344
250 1043 8344
251 1043 8344
252 1043 8344
253 1043 8344
254 1043 8344
255 1043 8344
256 1043 8344
257 612 4896
10 Zeilen ausgewählt.
Hier entspricht die vsize sehr genau den Erwartungen, aber die Blocks sind offenbar trotzdem nur halb gefüllt. Im Blockdump sieht man nach einem Blockheader von ca. 2000 Zeichen folgende Muster:
... 011CD8720 41414141 0801002C 41414141 41414141 [AAAA,...AAAAAAAA] 011CD8730 0801002C 41414141 41414141 0801002C [,...AAAAAAAA,...] 011CD8740 41414141 41414141 0801002C 41414141 [AAAAAAAA,...AAAA] 011CD8750 41414141 0801002C 41414141 41414141 [AAAA,...AAAAAAAA] 011CD8760 0801002C 41414141 41414141 0801002C [,...AAAAAAAA,...] 011CD8770 41414141 41414141 0801002C 41414141 [AAAAAAAA,...AAAA] 011CD8780 41414141 0801002C 41414141 41414141 [AAAA,...AAAAAAAA] 011CD8790 0801002C 41414141 41414141 0801002C [,...AAAAAAAA,...] 011CD87A0 41414141 41414141 0801002C 41414141 [AAAAAAAA,...AAAA] ...
Offenbar ist die Speicherung für die Sätze weniger kompakt und die (row) directory Informationen sind umfangreicher, als ich das angenommen hätte. (Die verlinkte Seite erklärt "The row directory uses 2 bytes per stored row.", aber sicher zuordnen kann ich diese Struktur im Blockdump nicht)
Erwartungsgemäß lassen sich wenige große Sätze besser in den Block unterbringen:
SQL> create table t4
2 as
3 select rpad('*', 1000, '*') col4
4 from dual
5 connect by level <= 32;
Tabelle wurde erstellt.
SQL> select blockid
2 , count(*)
3 , sum(colsize)
4 from (select dbms_rowid.rowid_block_number(rowid) blockid
5 , vsize(col4) colsize
6 from t4)
7 group by blockid
8 order by blockid;
BLOCKID COUNT(*) SUM(COLSIZE)
---------- ---------- ------------
328 14 14000
329 14 14000
330 4 4000
Für kleine Rows ist der Overhead des row directory denmach recht signifikant, für größere spielt er eine weniger wichtige Rolle.
Keine Kommentare:
Kommentar veröffentlichen