热块概述
当一个会话需要访问一个数据块,而这个数据块正在被另一个用户从磁盘读取到内存中或者这个数据块正在被另一个会话修改时,当前的会话就需要等待,就会产生一个buffer busy waits等待,也伴随着Latch争用。如果太多的会话去访问相同的数据块导致长时间的
buffer busy waits等待
,通常表现形式为CPU使用率很高,但吞吐量很低。造成热快的原因可能是数据库设置导致或者重复执行的SQL 频繁访问一些相同的数据块导致。热块产生的原因不尽相同,按照数据块的类型,可以分成以下几种热块类型,不同热块类型处理的方式都是不同的:表数据块、索引数据块、索引根数据块、文件头数据块和数据块自身的争用。
表数据块
比如在OLTP系统中,对于一些小表,会出现某些数据块被频繁查询或者修改的操作,这时候这些被频繁访问的数据块就会变成热块,导致内存中Latch的争用。
如果出现这样的热块情况,并且表不太大,一个方法是可以考虑将表数据分布在更多的数据块上,减少数据块被多数会话同时访问的频率。
可以通过下面的命令将每个数据块存放记录的数量减到最少:
alter table minimize records_per_block;
我们也可以通过调大PCTFREE来实现,不过在调整PCTFREE时,
我们要注意的是,这个参数虽然是可以动态调整的,但是我们调整PCTFREE参数只能对新的数据插入起作用,对于已经填充过满的老数据块,是无法起作用的,数据分布问题,必须调整参数后,对表进行重组,才能对表中的所有数据块都起作用。对表重组的办法有很多,比如ALTER TABLE ... MOVE或者EXP/IMP等。
除了调整
PCTFREE外,
减少热块冲突的更好的办法是将这张表放在BLOCK_SIZE较小的表空间里。以上所有的方法都是将数据尽可能地分布到多个数据块为指导思想进行实现的。
请看下面的例子,创建两个数据量相同的表,让一个表上每个数据块存放记录数尽可能地小,另一个表保持默认的情况,来看数据块访问情况:
SQL> create table t as select * from dba_objects;
Table created.
SQL> create index t_inx on t(object_id);
Index created.
SQL> exec dbms_stats.gather_table_stats(‘HR','T',cascade=>true);
PL/SQL procedure successfully completed.
SQL> select 'T' tbl_name, rows_per_block,