pe from dba_segments where segment_name like 'ZLM%';
SEGMENT_NA HEADER_FILE HEADER_BLOCK BLOCKS BYTES EXTENTS MIN_EXTENTS MAX_EXTENTS SEGMENT_TYPE ---------- ----------- ------------ ---------- ---------- ---------- ----------- ----------- ------------------ ZLM2 6 1282 1152 9437184 24 1 2147483645 TABLE ZLM1 6 130 8 65536 1 1 2147483645 TABLE
用truncate清空表数据之后,高水位立即下降到8了,8个block共占用64k,1个extent
--重新分析测试表ZLM2并查看数据块占用情况 SQL> analyze table zlm.zlm1 compute statistics;
Table analyzed.
SQL> select table_name,num_rows,blocks,empty_blocks,avg_row_len,last_analyzed from dba_tables where table_name like 'ZLM%';
TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS AVG_ROW_LEN LAST_ANALYZED ------------------------------ ---------- ---------- ------------ ----------- ------------------ ZLM2 75541 1101 51 100 27-SEP-14 ZLM1 0 0 8 0 27-SEP-14
--查看数据块和extent分布情况 SQL> select block_id,extent_id,bytes,blocks from dba_extents where segment_name like 'ZLM1';
BLOCK_ID EXTENT_ID BYTES BLOCKS ---------- ---------- ---------- ---------- 128 0 65536 8
可以看到,虽然测试表ZLM1中已经没有数据,但是还是会占用8个数据块的高水位,也就是说,当你创建一个空表,即只建立表结构的时候,
Oracle就会给这个表分配至少一个extent,默认为8,可以通过参数调整这个默认值
SQL> select block_id,extent_id,bytes,blocks from dba_extents where segment_name like 'ZLM2';
BLOCK_ID EXTENT_ID BYTES BLOCKS ---------- ---------- ---------- ---------- 1280 0 65536 8 1288 1 65536 8 1296 2 65536 8 1304 3 65536 8 1312 4 65536 8 1320 5 65536 8 1328 6 65536 8 1336 7 65536 8 1344 8 65536 8 1352 9 65536 8 1360 10 65536 8 1368 11 65536 8 1376 12 65536 8 1384 13 65536 8 1392 14 65536 8 1400 15 65536 8 1408 16 1048576 128 1536 17 1048576 128 1664 18 1048576 128 1792 19 1048576 128 1920 20 1048576 128 2048 21 1048576 128 2176 22 1048576 128 2304 23 1048576 128
--创建测试表ZLM3并插入数据查看数据块分配情况
SQL> create table zlm.zlm3 as select * from zlm.zlm2;
Table created.
SQL> select segment_name,header_file,header_block,blocks,bytes,extents,min_extents,max_extents,segment_type from dba_segments where segment_name like 'ZLM%';
SEGMENT_NA HEADER_FILE HEADER_BLOCK BLOCKS BYTES EXTENTS MIN_EXTENTS MAX_EXTENTS SEGMENT_TYPE ---------- ----------- ------------ ---------- ---------- ---------- ----------- ----------- ------------------ ZLM3 6 138 1152 9437184 24 1 2147483645 TABLE ZLM2 6 1282 1152 9437184 24 1 2147483645 TABLE ZLM1 6 130 8 65536 1 1 2147483645 TABLE
SQL> select block_id,extent_id,bytes,blocks from dba_extents where segment_name like 'ZLM3';
BLOCK_ID EXTENT_ID BYTES BLOCKS ---------- ---------- ---------- ---------- 136 0 65536 8 144 1 65536 8 152 2 65536 8 160 3 65536 8 168 4 65536 8 176 5 65536 8 184 6 65536 8 192 7 65536 8 200 8 65536 8 208 9 65536 8 216 10 65536 8 224 11 65536 8 232 12 65536 8 240 13 65536 8 248 14 65536 8 256 15 65536 8 384 16 1048576 128 512 17 1048576 128 640 18 1048576 128 768 19 1048576 128 896 20 1048576 128 1024 21 1048576 128 1152 22 1048576 128 2432 23 1048576 128
在降低了测试表空间中的高水位后,新创建的表会从第138块开始分配header_block空间,而不是1282+1152=2434,注意这里header_block的值依然会比此表extent中分配的第一个block的值要大2,而2434-2正好等于2432,也就是该表分配到的最后一个extent中block的起始id,通过truncate,可以重新把原来应该由测试表ZLM1占用的那部分block空间释放出来,给测试表ZLM3的extent,用于分配block
总结:
本测试只是验证了delete和truncate对于高水位的影响,与减少磁盘碎片及空间释放的概念并不是很相关,其实用truncate降低高水位来释放磁盘空间的作用是很有限的,我们关注高水位的主要目的,不是去减少浪费磁盘空间,而是出于性能上的考虑,由于高水位的存在,一旦对表做全表扫描,就会使性能大大降低,即使只是一张空的表,如果要真正减少表空间碎片,减少磁盘占用空间,更有效的方法是使用move或shrink(10g or higher),甚至expdp导出再impdp倒入等方法,这里就不一一举例了,当然了,这些方法也都是降低高水位的有效手段。
|