一次IO利用率100%,数据库大量全表扫描问题

标签: io 利用 数据库 | 发表时间:2012-09-21 16:54 | 作者:hijk139
出处:http://blog.csdn.net
现象描述
 1, 具体什么业务受到影响不清楚,但从系统测看,主机IO资源比较紧张(HPUX 11.31 +oracle 9i)
HP-UX crmdb3 B.11.23 U ia64    09/19/12

11:09:42    %usr    %sys    %wio   %idle
11:09:45      28       5      64       3
11:09:48      28       2      61       9
11:09:51      28       2      67       3
11:09:54      33       2      57       7
11:09:57      31       2      59       7

glance看IO已接近100%

2,数据库侧看,大量db file scattered read IO相关等待事件

 SID    SERIAL# OSUSER   USERNAME SVRPROC                              SQL_HASH_VALUE EVENT                                             P1         P2         P3
------ ---------- -------- -------- ------------------------------------ -------------- ------------------------------ --------------------- ---------- ----------
    89      28200 airsm    ai    10261                                     664153718 db file scattered read                            37     192750          8
   159      43064 airsm    ai    26996                                    3295997871 db file scattered read                            36      60587          8
   173       8048 airsm    ai    3250                                     1002585284 db file scattered read                            36      75123          8
   458      18261 airsm    ai    2505                                     2812298138 db file scattered read                            36     365179          8
……..
 

3,等待的sql具体如下,主要原因是对ai.RM_A_x全表扫描,该表72GB大小。

SQL> @get_sql_by_hv
Enter value for hv: 1775869170
old   3:  where hash_value = '&HV'
new   3:  where hash_value = '1775869170'

SQL Text
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
select a.serial_num, x.c_attr_1 crypto, to_char(a.expirt_dt, 'yy
yy-mm-dd') expirt_dt, k.key_info     from RM_A_x x, RM_A
 a, RM_A_key_info k
 where a.row_id = x.row_id (+)
                                   and k.row_id(+) = x.n_attr_1
                                                               a
nd serial_num in (  '12475014246302465', '12475014246302485', '1
2475014246302572', '12475014246302595', '12475014246302599', '12
475014246302620', '12475014246302636', '12475014246302765')

9 rows selected.

SQL> /
Enter value for hv: 2144161010
old   3:  where hash_value = '&HV'
new   3:  where hash_value = '2144161010'

SQL Text
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
select a.serial_num, x.c_attr_1 crypto, to_char(a.expirt_dt, 'yy
yy-mm-dd') expirt_dt, k.key_info     from RM_A_x x, RM_A
 a, RM_A_key_info k
 where a.row_id = x.row_id (+)
                                   and k.row_id(+) = x.n_attr_1
                                                               a
nd serial_num in (  '12475014246306603', '12475014246306726', '1
2475014246306804')

8 rows selected.

SQL>  select bytes/1024/1024 M,owner from dba_segments where segment_name ='RM_A';

         M OWNER
---------- ------------------------------------------------------------------------------------------
     71206 ai
     
SQL> @showplan_9i
Enter value for hash: 125827763
old  29: hash_value='&hash'
new  29: hash_value='125827763'

Optimizer Plan:
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Operation | PHV/Object Name | Rows | Bytes| Cost |
|SELECT STATEMENT                |----- 125827763 [0]
-|       |      |        |

|NESTED LOOPS OUTER              |                     |       |      |        |
| NESTED LOOPS OUTER             |                     |       |      |        |
|  TABLE ACCESS FULL             |RM_A             |       |      |        |
|  TABLE ACCESS BY INDEX ROWID   |RM_A_X           |       |      |        |
|   INDEX UNIQUE SCAN            |RM_A_X_P1        |       |      |        |
| TABLE ACCESS BY INDEX ROWID    |RM_A_KEY_INFO    |       |      |        |
|  INDEX UNIQUE SCAN             |RM_A_KEY_INFO_P1 |       |      |        |



原因分析

1,该表有相关索引,RM_A_M1对应SERIAL_NUM列的索引,字段类型也匹配

Index           Column                     Col Column
Name            Name                       Pos Details
--------------- ------------------------- ---- ------------------------
RM_A_F1     BUCKET_ID                    1 NUMBER(15,0)
                BUCKET_ID                    1 NUMBER(15,0)
RM_A_F2     INV_ID                       1 NUMBER(15,0)
                INV_ID                       1 NUMBER(15,0)
RM_A_M1     SERIAL_NUM                   1 VARCHAR2(80)
                SERIAL_NUM                   1 VARCHAR2(80)
               
2,为什么不走索引呢.原来是使用基于rule类型的优化器,RULE优化器根据FROM列表中的位置来选择驱动表,FROM列表中最后一个表被作为驱动表。

SQL>  select OPTIMIZER_MODE from  v$sqlarea where HASH_VALUE='125827763';

OPTIMIZER_MODE
---------------------------------------------------------------------------
RULE

Table                   Number                 Empty Average    Chain Average Global User           Sample Date
Name                   of Rows   Blocks       Blocks   Space    Count Row Len Stats  Stats            Size MM-DD-YYYY
--------------- -------------- -------- ------------ ------- -------- ------- ------ ------ -------------- ----------
RM_A_X                                                                    NO     NO

SQL>  select CREATED,OBJECT_NAME from  dba_objects where object_name ='RM_A_X' and owner='ai';

CREATED                                                                                              OBJECT_NAME
---------------------------------------------------------------------------------------------------- --------------------
2012-06-26 09:52:48                                                                                  RM_A_X

SQL> show parameter optimizer_mode

NAME                                 TYPE                              VALUE
------------------------------------ --------------------------------- ------------------------------
optimizer_mode                       string                            RULE

3,rbo的执行顺序如下,安装如下文章所述,IN应该属于rank 10,如果把in改成单条件=则直接走相关索引

sing the RBO, the optimizer chooses an execution plan based on the access paths available and the ranks of these access paths. Oracle's ranking of the access paths is heuristic. If there is more than one way to execute a SQL statement, then the RBO always uses the operation with the lower rank. Usually, operations of lower rank execute faster than those associated with constructs of higher rank.
The list shows access paths and their ranking:
RBO Path 1: Single Row by Rowid
RBO Path 2: Single Row by Cluster Join
RBO Path 3: Single Row by Hash Cluster Key with Unique or Primary Key
RBO Path 4: Single Row by Unique or Primary Key
RBO Path 5: Clustered Join
RBO Path 6: Hash Cluster Key
RBO Path 7: Indexed Cluster Key
RBO Path 8: Composite Index
RBO Path 9: Single-Column Indexes
RBO Path 10: Bounded Range Search on Indexed Columns
RBO Path 11: Unbounded Range Search on Indexed Columns
RBO Path 12: Sort Merge Join
RBO Path 13: MAX or MIN of Indexed Column
RBO Path 14: ORDER BY on Indexed Column
RBO Path 15: Full Table Scan

解决方案:


  由于问题比较紧急,需要尽快解决,因此使用了最简单有效的解决办法用hint,使用此方法修改sql后问题很快解决。
  SQL> explain plan for
  2  select /*+index(a RM_A_M1) */ a.serial_num, x.c_attr_1 crypto, to_char(a.expirt_dt, 'yyyy-mm-dd') expirt_dt, k.key_info     from  ai.RM_A_key_info k ,ai.RM_A_x x ,ai.RM_A
  3   a where a.row_id = x.row_id (+)
  4  and k.row_id(+) = x.n_attr_1        and serial_num in (  '12475014246300079', '12475014246300099');

Explained.

SQL>  select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------
| Id  | Operation                      |  Name                 | Rows  | Bytes | Cost  |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |                       |     2 |  6204 |     9 |
|   1 |  NESTED LOOPS OUTER            |                       |     2 |  6204 |     9 |
|   2 |   NESTED LOOPS OUTER           |                       |     2 |  4126 |     7 |
|   3 |    INLIST ITERATOR             |                       |       |       |       |
|   4 |     TABLE ACCESS BY INDEX ROWID| RM_A              |     2 |    70 |     5 |
|*  5 |      INDEX RANGE SCAN          | RM_A_M1           |     2 |       |     4 |
|   6 |    TABLE ACCESS BY INDEX ROWID | RM_A_X            |     1 |  2028 |     1 |

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|*  7 |     INDEX UNIQUE SCAN          | RM_A_X_P1         |     1 |       |       |
|   8 |   TABLE ACCESS BY INDEX ROWID  | RM_A_KEY_INFO     |     1 |  1039 |     1 |
|*  9 |    INDEX UNIQUE SCAN           | RM_A_KEY_INFO_P1  |     1 |       |       |
----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   5 - access("A"."SERIAL_NUM"='12475014246300079' OR
              "A"."SERIAL_NUM"='12475014246300099')
   7 - access("A"."ROW_ID"="X"."ROW_ID"(+))

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   9 - access("K"."ROW_ID"(+)="X"."N_ATTR_1")

Note: cpu costing is off

25 rows selected.


参考资料

http://docs.oracle.com/cd/B10501_01/server.920/a96533/rbo.htm#39232


作者:hijk139 发表于2012-9-21 16:54:09 原文链接
阅读:0 评论:0 查看评论

相关 [io 利用 数据库] 推荐:

一次IO利用率100%,数据库大量全表扫描问题

- - CSDN博客推荐文章
 1, 具体什么业务受到影响不清楚,但从系统测看,主机IO资源比较紧张(HPUX 11.31 +oracle 9i). glance看IO已接近100%. 2,数据库侧看,大量db file scattered read IO相关等待事件. 3,等待的sql具体如下,主要原因是对ai.RM_A_x全表扫描,该表72GB大小.

MySQL数据库的IO操作

- - haohtml's blog
         淘宝丁奇分享的PPT:MySQL数据库的IO操作,详细分享了四块的内容,并且告诉大家如何调整MySQL数据库IO操作相关的参数,给出了详细的选择策略,现替其整理成文章分享与此. 4.影响io行为的一些参数和选择策略. 一个简单的查询 select * from t where id>=(  select id from t where k1=100 limit 100000,1) limit 2;.

淘宝海量数据库之六-克服随机IO难题

- William - 阳振坤的博客
与传统磁盘相比,SSD固态盘提供了非常好的随机读性能,单盘可达35000IOPS (4KB)甚至更高,并提供512MB/s或以上的读出带宽. 但通常SSD盘的随机写性能甚至比一般磁盘更差,这是因为,尽管SSD的读和写都以4KB页(page)为单位,但SSD写入前需要先擦除已有内容,而擦除以块(block)为单位,一个块(block)通常是128个连续的页(page),即512KB.

转:数据库如何抵抗随机IO:问题、方法与现实

- {ZuiZui} - 唐福林-博客雨
随机IO几乎是令所有DBA谈虎色变的一个问题,这个问题,往往在数据量小的时候不出现,在数据量超过内存大小时,才陡然出现,令没有经验的DBA促不及防,也令有经验的DBA寝食难安. 传统的数据库架构对随机IO几乎没有还手之力. 传统数据库的核心通常是页级缓存、B+树、堆或索引组织表,这些机制,对随机IO的抵抗能力,都无一例外的可悲的差.

数据库如何抵抗随机IO:问题、方法与现实

- crystal - 风轻扬
随机IO几乎是令所有DBA谈虎色变的一个问题,这个问题,往往在数据量小的时候不出现,在数据量超过内存大小时,才陡然出现,令没有经验的DBA促不及防,也令有经验的DBA寝食难安. 传统的数据库架构对随机IO几乎没有还手之力. 传统数据库的核心通常是页级缓存、B+树、堆或索引组织表,这些机制,对随机IO的抵抗能力,都无一例外的可悲的差.

当内存512遇上Access数据库600M,IO磁盘受伤了

- - 博客园_首页
服务器内存就512M,Access数据库(文章库)600多M,结果竟然就是IO受伤了. 秋色园技术原理解析 系列,园里不少看过的帅歌,应该有点印象,从开始到现在,还是铁打的Access数据库. 虽然本人目前对Access恨入之骨,皆因囊中羞涩,暂时不得不与之同流合污. 忙碌 微博粉丝精灵几个月来, 秋色园一直运行正常,除了远程界面都变的很卡之外,基本上也没发现什么异常.

可伸缩Web架构的4个问题:瓶颈,CPU,数据库,IO

- - 互联网 - ITeye博客
在这篇文章中我将谈到关于大规模网站架构扩展和性能方面的一些问题. 首先让我们先来了解一些术语. 稍后我将对Web应用扩展过程中所遇到的不同问题进行讲解,例如:. Web系统的性能受多方面因素的影响,但大多数开发人员主要关心的是响应时间和可扩展性这两方面. 响应时间是指Web应用从收到请求到返回响应结果所花费的时间.

物理IO与逻辑IO

- - 操作系统 - ITeye博客
IO性能对于一个系统的影响是至关重要的. 一个系统经过多项优化以后,瓶颈往往落在数据库;而数据库经过多种优化以后,瓶颈最终会落到IO. 而IO性能的发展,明显落后于CPU的发展. Memchached也好,NoSql也好,这些流行技术的背后都在直接或者间接地回避IO瓶颈,从而提高系统性能. 上图层次比较多,但总的就是三部分.

利用 index、explain和profile优化mysql数据库查询小结

- - 博客园_首页
想必大家对index,explain和profile的利用也很多,这是我最近两天优化mysql语句查询资料整理的一些内容,希望大家可以一起来补充一下. 1.最好是在相同类型的字段间进行比较的操作. 在MySQL 3.23版之前,这甚至是一个必须的条件. 例如不能将一个建有索引的INT字段和BIGINT字段进行比较;但是作为特殊的情况,在CHAR类型的字段和VARCHAR类型字段的字段大小相同的时候,可以将它们进行比较.

利用kettle组件导入excel文件到数据库

- - CSDN博客数据库推荐文章
利用kettle组件导入excel文件到数据库.        把excel文件内容导入到目标表中;然后用java调用kettle的转换. excel文件的内容只有两列,示例如下:.        数据库表的结构如下:. 使用oracle函数解决上图黄色行的字段:两个uuid和两个系统日期;. 需要生成uuid,这个在oracle中可以利用SYS_UUID()函数实现;.