ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 表热块的处理手段分析

表热块的处理手段分析

原创 Linux操作系统 作者:尛样儿 时间:2010-09-11 18:30:57 0 删除 编辑

前言:
热块在我们的日常数据库中,是最常见的问题之一,怎样来解决问题,没有一个统一的方法,只有通过实验,结合实际情况来减少热块的发生,下面来分析一下几种能够解决热块的手段之间的不同。
热块是由于同时访问某些块太过频繁而出现的性能问题。从这一点来说,我们可以让块所包含的数据少一点,那么访问数据的用户就会分散到不同的块上。还有就是我们可以通过hash算法来将连续插入的数据分散存储在不同的块中,这样用户访问数据也会分散到不同的块上。

//创建普通表
SQL> create table test111
  2  (id number,
  3  name varchar2(20));

//指定pctfree的表
create table test222
(id number,
name varchar2(20))
pctfree 60
;

//创建hash表
CREATE TABLE test333
(id number,
name varchar2(20))
PARTITION BY HASH (id)(
PARTITION pid1,
PARTITION pid2,
PARTITION pid3,
PARTITION pid4,
PARTITION pid5,
PARTITION pid6,
PARTITION pid7,
PARTITION pid8,
PARTITION pid9,
PARTITION pid10
);

//创建普通表,指定minimize records_per_block属性
create table test444
(id number,
name varchar2(20));
alter table test444 minimize records_per_block;
Table created.

SQL>   2    3    4    5
Table created.

SQL>   2    3    4    5    6    7    8    9   10   11   12   13   14   15
Table created.

SQL>   2    3
Table created.

SQL> alter table test444 minimize records_per_block;
alter table test444 minimize records_per_block
            *
ERROR at line 1:
ORA-28603: statement not permitted on empty tables

SQL> insert into test444 values (111,'111');

1 row created.

SQL> commit;

Commit complete.

SQL> alter table test444 minimize records_per_block;

Table altered.

SQL> truncate table test444;

Table truncated.

//创建模拟数据
SQL> create or replace procedure p_test
  2  as
  3  begin
  4  for i in 1..100000 loop
  5  insert into test111 values (i,to_char(i));
  6  insert into test222 values (i,to_char(i));
  7  insert into test333 values (i,to_char(i));
  8  insert into test444 values (i,to_char(i));
  9  commit;
 10  end loop;
 11  end p_test;
 12  /

Procedure created.

SQL> exec p_test;

PL/SQL procedure successfully completed.

SQL> commit;

Commit complete.

//分析1:4种不同类型的表,占用的块数
SQL> select count(distinct dbms_rowid.ROWID_BLOCK_NUMBER(rowid)) from test111 ;

COUNT(DISTINCTDBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID))
---------------------------------------------------
                                                218

SQL> select count(distinct dbms_rowid.ROWID_BLOCK_NUMBER(rowid)) from test222;

COUNT(DISTINCTDBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID))
---------------------------------------------------
                                                492

SQL> select count(distinct dbms_rowid.ROWID_BLOCK_NUMBER(rowid)) from test333;

COUNT(DISTINCTDBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID))
---------------------------------------------------
                                                221

SQL> select count(distinct dbms_rowid.ROWID_BLOCK_NUMBER(rowid)) from test444;

COUNT(DISTINCTDBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID))
---------------------------------------------------
                                              50000

//4种不同类型的表,块包含的行数分析
SQL> select tt.block_rows,count(1) from (
select dbms_rowid.ROWID_BLOCK_NUMBER(rowid) blockid,count(1) block_rows from test111 group by dbms_rowid.ROWID_BLOCK_NUMBER(rowid))
tt group by tt.block_rows;  2    3

BLOCK_ROWS   COUNT(1)
---------- ----------
       574          1
       155          1
       461          1
       549          1
       519         17
       454        197

6 rows selected.

SQL> select tt.block_rows,count(1) from (
select dbms_rowid.ROWID_BLOCK_NUMBER(rowid) blockid,count(1) block_rows from test222 group by dbms_rowid.ROWID_BLOCK_NUMBER(rowid))
tt group by tt.block_rows;
  2    3
BLOCK_ROWS   COUNT(1)
---------- ----------
       247          3
       209          1
       229         39
       262          1
       201        447
        10          1

6 rows selected.

SQL>
SQL> select tt.block_rows,count(1) from (
select dbms_rowid.ROWID_BLOCK_NUMBER(rowid) blockid,count(1) block_rows from test333 group by dbms_rowid.ROWID_BLOCK_NUMBER(rowid))
tt group by tt.block_rows;
  2    3
BLOCK_ROWS   COUNT(1)
---------- ----------
       399          1
        91          1
       485          1
       472          1
       470          1
       529          2
       155          1
       481          1
       523          1
       230          1
       331          1

BLOCK_ROWS   COUNT(1)
---------- ----------
       532          1
       467          2
       464          1
       528          1
       519          6
       483          1
       525          2
       277          1
       473          1
       381          1
       454        185

BLOCK_ROWS   COUNT(1)
---------- ----------
       530          2
       203          1
       480          1
       524          1
       406          2

27 rows selected.

SQL> select tt.block_rows,count(1) from (
select dbms_rowid.ROWID_BLOCK_NUMBER(rowid) blockid,count(1) block_rows from test444 group by dbms_rowid.ROWID_BLOCK_NUMBER(rowid))
tt group by tt.block_rows;
  2    3
BLOCK_ROWS   COUNT(1)
---------- ----------
         2      50000

SQL>

分析:从上面的分析来看,普通表,每个块都包含了400~500行记录。使用了pctfree的块大部分只包含了200~250行记录。hash表的大部分块也包含了400~500行记录。指定指定minimize records_per_block属性的表最规矩,没个块只包含了2条记录。
从以上的数据统计来看,指定minimize records_per_block属性的方式不可取,这样会导致读块的个数增加数倍,对io压力太大。使用pctfree达到了我们的目的,减少块所包含的数据量。hash表跟普通表大部分块所包含的数据量都是相近的。但是我们要注意一点,hash表所包含的数据并不是有序的,从这一点来说,对热块的解决也是有帮助的。
从以上的分析来看,pctfree可以减少块包含的行数,hash表可以打乱连续插入数据的分布情况,这2种手段都可以缓解热块情况。我们何不把这2种手段结合起来用呢?

SQL>
SQL>
SQL> create table test555
(id number,
name varchar2(20))
pctfree 60
PARTITION BY HASH (id)(
PARTITION pid1,
PARTITION pid2,
PARTITION pid3,
PARTITION pid4,
PARTITION pid5,
PARTITION pid6,
PARTITION pid7,
PARTITION pid8,
PARTITION pid9,
PARTITION pid10
);  2    3    4    5    6    7    8    9   10   11   12   13   14   15   16

Table created.

SQL>
create or replace procedure p_test
as
begin
for i in 1..100000 loop
insert into test555 values (i,to_char(i));
commit;
end loop;
end p_test;
/
SQL>   2    3    4    5    6    7    8    9
Procedure created.

SQL> exec p_test

PL/SQL procedure successfully completed.

 

SQL> select count(distinct dbms_rowid.ROWID_BLOCK_NUMBER(rowid) ) from test555;

COUNT(DISTINCTDBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID))
---------------------------------------------------
                                                496

SQL> select tt.block_rows,count(1) from (
select dbms_rowid.ROWID_BLOCK_NUMBER(rowid) blockid,count(1) block_rows from test555 group by dbms_rowid.ROWID_BLOCK_NUMBER(rowid))
tt group by tt.block_rows;  2    3

BLOCK_ROWS   COUNT(1)
---------- ----------
       153          1
       213          1
       235          1
       218          2
       229         27
       205          1
       224          1
       201        388
       240          2
       161          1
       230          1

BLOCK_ROWS   COUNT(1)
---------- ----------
       135          1
       242          1
       239          2
       206          1
        75          1
         8          1
       200         50
       214          1
       107          1
       241          1
        99          1

BLOCK_ROWS   COUNT(1)
---------- ----------
       221          2
       216          1
       236          1
       158          2
         9          1
       234          2

28 rows selected.

用这种方式,既保证了每个块包含的行数减少,也保证了连续的数据分布在不同的块中存储。笔者觉得用这种方式来实现表的创建能够最大程度的把对数据的访问分散到表所包含的所有块上,也减少了块包含的数据。这需要实践来检验。至于pctfree和hash分区的个数,也没有什么固定值,需要dba通过经验和系统的情况来调整,当然最有效的办法就是测试了。通过测试来找到一个最佳值。

RAC全局热块的处理手段可参考文章:http://blog.csdn.net/csucxcc/article/details/5896309

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/23135684/viewspace-673241/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
Oracle数据库管理员,Oracle数据库系统构架员;2012年7月出版《构建最高可用Oracle数据库系统:Oracle 11gR2 RAC管理、维护与性能优化》一书;Oracle 10g OCM。

注册时间:2010-01-05

  • 博文量
    483
  • 访问量
    5650874