今天在看关于undo的章节的时候遇到HWM(high-water mark)这个概念,以前隐约有听过,但并未深入了解,查了些相关解释并自己动手做了下实验。
概念了解:
在Oracle数据的存储中,可以把存储空间想象为一个水库,数据想象成书库中的水。水库中水的位置有一条线叫做水位线,在Oracle中这条线被称为高水位线(HWM)。在数据库表刚建立的时候,由于没有任何数据,HWM=0(最低值)。当插入数据以后,HWM会上涨,需要注意的是就算用DELETE语句删除数据,HWM也不会下降,即HWM在日常的增删操作中只会上涨不会下跌。
在执行SELECT语句时,SELECT会对表中的数据进行一次扫描,ORACLE会扫描HWM一下的数据块,而不是说数据库中有多少数据就扫描这么大的数据块(也许平时应用中遇到的查询速度慢可能就跟这个原因有关,但当时没有这个概念````)
如何知道一个表的HWM呢?
1.先对表进行分析:
ANALYZE TABLE T ESTIMATE STATISTICS;
2.
SELECT table_name,num_rows,blocks,empty_blocks
FROM user_tables
WHERE table_name='T';
FROM user_tables
WHERE table_name='T';
TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS
------------------------------ ---------- ---------- ------------
T 100 684 83
------------------------------ ---------- ---------- ------------
T 100 684 83
BLOCKS 列代表该表中曾经使用过的数据块的数目,即水线。
EMPTY_BLOCKS 代表分配给该表,但在水线以上的数据块,即从来没有使用的数据块。
SQL> SELECT segment_type,blocks ,extents
2 FROM dba_segments
3 WHERE segment_name='T' and WNER='SYS';
2 FROM dba_segments
3 WHERE segment_name='T' and WNER='SYS';
SEGMENT_TYPE BLOCKS EXTENTS
------------------ ---------- ----------
TABLE 768 21
------------------ ---------- ----------
TABLE 768 21
BLOCKS + EMPTY_BLOCKS(684+83=767)比dba_segments .BLOCKS(768)少一个数据块,这是因为有一个数据块被保留作为segment header。
DBA_SEGMENTS.BLOCKS 表示分配给这个表的所有的数据库块的数目。USER_TABLES.BLOCKS表示已经使用过的数据库块的数目。
SQL> SELECT COUNT (DISTINCT
2 DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid)||
3 DBMS_ROWID.ROWID_RELATIVE_FNO(rowid)) "Used Blocks"
4 FROM t;
2 DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid)||
3 DBMS_ROWID.ROWID_RELATIVE_FNO(rowid)) "Used Blocks"
4 FROM t;
Used Blocks
-----------
2 -----------表示目前表t有两个数据块里有数据
-----------
2 -----------表示目前表t有两个数据块里有数据
SQL> delete t;
已删除100行。
SQL> commit;
提交完成。
SQL> ANALYZE TABLE T ESTIMATE STATISTICS;
表已分析。
SQL> SELECT table_name,num_rows,blocks,empty_blocks
2 FROM user_tables
3 WHERE table_name='T';
2 FROM user_tables
3 WHERE table_name='T';
TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS
------------------------------ ---------- ---------- ------------
T 0 684 83
-------此时表中已无数据,但是使用的数据块没有变化
------------------------------ ---------- ---------- ------------
T 0 684 83
-------此时表中已无数据,但是使用的数据块没有变化
SQL> SELECT COUNT (DISTINCT
2 DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid)||
3 DBMS_ROWID.ROWID_RELATIVE_FNO(rowid)) "Used Blocks"
4 FROM t;
2 DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid)||
3 DBMS_ROWID.ROWID_RELATIVE_FNO(rowid)) "Used Blocks"
4 FROM t;
Used Blocks
-----------
0
------说明没有任何数据块中有数据
-----------
0
------说明没有任何数据块中有数据
如何降低HWM?
采用TRUNCATE进行删除数据
SQL> truncate table t;
表被截断。
SQL> ANALYZE TABLE T ESTIMATE STATISTICS;
表已分析。
SQL> SELECT table_name,num_rows,blocks,empty_blocks
2 FROM user_tables
3 WHERE table_name='T';
2 FROM user_tables
3 WHERE table_name='T';
TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS
------------------------------ ---------- ---------- ------------
T 0 0 7
------------------------------ ---------- ---------- ------------
T 0 0 7
SQL> SELECT segment_type,blocks ,extents
2 FROM dba_segments
3 WHERE segment_name='T';
2 FROM dba_segments
3 WHERE segment_name='T';
SEGMENT_TYPE BLOCKS EXTENTS
------------------ ---------- ----------
TABLE 8 1
------------------ ---------- ----------
TABLE 8 1
*****TRUNCATE命令回收了由DELETE命令产生的空闲空间,该表分配的空间由原先的768块降为8块。
为了保留由delete命令产生的空闲空间,可以使用
TRUNCATE TABLE T REUSE STORAGE
为了保留由delete命令产生的空闲空间,可以使用
TRUNCATE TABLE T REUSE STORAGE
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10314474/viewspace-616236/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/10314474/viewspace-616236/