SQL质量差导致逻辑读比较多


1、最近日常检查查看awr报告,发现由一个索引的逻辑读很大

  Tablespace                      Subobject  Obj.       Logical

  Owner         Name    Object Name            Name     Type         Reads  %Total

  ---------- ---------- -------------------- ---------- ----- ------------ -------

  BASECONF   TBS_DEFALU PK_USER_TO_CHANNEL              INDEX   10,318,512   16.95

  VIPBILL    TBS_DEFALU BIL_COLLECT_BIT                 TABLE    6,285,648   10.33

  BASECONF   DATA_04    LAYER_CHANNEL_TO_NOD            TABLE    6,042,416    9.93

  BASECONF   DATA_04    PK3_1                           INDEX    3,952,688    6.49

  LOGBILL    TBS_BAND_D IX_DAILYTABLE_ALL    P20080704  INDEX    3,575,488    5.87

  2、表结构如下:

  -- Create table

  create table USER_TO_CHANNEL

  (

  USER_ID    NUMBER(4) not null,

  CHANNEL_ID CHAR(4) not null,

  constraint PK_USER_TO_CHANNEL primary key (USER_ID, CHANNEL_ID)

  )

  organization index;

  这是一个索引组织表,表的所有字段组成一个主键索引,用索引组织表是没有问题的。

  3、查找top sql发现有如下sql操作USER_TO_CHANNEL

  1,404,990          335      4,194.0    2.3     6.48      6.67 garq0xt0u3tkp

  Module: JDBC Thin Client

  select A.CHANNEL_ID, B.CHANNEL_NAME from USER_TO_CHANNEL A,PUB_CHANNEL B where A

  .USER_ID=283 and A.CHANNEL_ID=B.CHANNEL_ID and B.CHANNEL_TYPE='HTTP'

  SQL> select count(*) from USER_TO_CHANNEL;

  COUNT(*)

  ----------

  4259

  SQL> select count(*) from PUB_CHANNEL;

  COUNT(*)

  ----------

  4260

  SQL>

  4、查看sql的执行计划

  SQL> set autotrace traceonly;

  SQL> select A.CHANNEL_ID, B.CHANNEL_NAME

  2    from USER_TO_CHANNEL A, PUB_CHANNEL B

  3   where A.USER_ID = 283

  4     and A.CHANNEL_ID = B.CHANNEL_ID

  5     and B.CHANNEL_TYPE = 'HTTP';

  33 rows selected.

  Execution Plan

  ----------------------------------------------------------

  -------------------------------------------------------------------------

  | Id  | Operation          | Name               | Rows  | Bytes | Cost  |

  -------------------------------------------------------------------------

  |   0 | SELECT STATEMENT   |                    |    34 |  1496 |    25 |

  |   1 |  NESTED LOOPS      |                    |    34 |  1496 |    25 |

  |   2 |   TABLE ACCESS FULL| PUB_CHANNEL        |  4053 |   142K|    24 |

  |   3 |   INDEX UNIQUE SCAN| PK_USER_TO_CHANNEL |     1 |     8 |     0 |

  -------------------------------------------------------------------------

  Note

  -----

  - 'PLAN_TABLE' is old version

  Statistics

  ----------------------------------------------------------

  0  recursive calls

  0  db block gets

  4194  consistent gets

  0  physical reads

  0  redo size

  2273  bytes sent via SQL*Net to client

  514  bytes received via SQL*Net from client

  4  SQL*Net roundtrips to/from client

  0  sorts (memory)

  0  sorts (disk)

  33  rows processed

  oracle默认采用NL进行全表扫描

  此时的逻辑读=consistent gets+db block gets=4194

  5、在sql语句中加入hint(1)

  SQL> select /*+use_hash(b,a)*/ A.CHANNEL_ID, B.CHANNEL_NAME

  2    from USER_TO_CHANNEL A, PUB_CHANNEL B

  3   where A.USER_ID = 283

  4     and A.CHANNEL_ID = B.CHANNEL_ID

  5     and B.CHANNEL_TYPE = 'HTTP';

  33 rows selected.

  Execution Plan
----------------------------------------------------------

  -------------------------------------------------------------------------

  | Id  | Operation          | Name               | Rows  | Bytes | Cost  |

  -------------------------------------------------------------------------

  |   0 | SELECT STATEMENT   |                    |    34 |  1496 |    27 |

  |   1 |  HASH JOIN         |                    |    34 |  1496 |    27 |

  |   2 |   INDEX RANGE SCAN | PK_USER_TO_CHANNEL |    34 |   272 |     2 |

  |   3 |   TABLE ACCESS FULL| PUB_CHANNEL        |  4053 |   142K|    24 |

  -------------------------------------------------------------------------

  Note

  -----

  - 'PLAN_TABLE' is old version

  Statistics

  ----------------------------------------------------------

  1  recursive calls

  0  db block gets

  112  consistent gets

  0  physical reads

  0  redo size

  2273  bytes sent via SQL*Net to client

  514  bytes received via SQL*Net from client

  4  SQL*Net roundtrips to/from client

  0  sorts (memory)

  0  sorts (disk)

  33  rows processed

  在sql语句中加入hint,此时的逻辑读有明显下降

  此时的逻辑读=consistent gets+db block gets=112

  6、在sql语句中加入hint(2)

  SQL> select /*+ use_nl(b,a) leading(a) */ A.CHANNEL_ID, B.CHANNEL_NAME

  2      from USER_TO_CHANNEL A, PUB_CHANNEL B

  3     where A.USER_ID = 283

  4       and A.CHANNEL_ID = B.CHANNEL_ID

  5       and B.CHANNEL_TYPE = 'HTTP';

  33 rows selected.

  Execution Plan

  ----------------------------------------------------------

  --------------------------------------------------------------------------------

  ---

  | Id  | Operation                    | Name               | Rows  | Bytes | Cost

  |

  --------------------------------------------------------------------------------

  ---

  |   0 | SELECT STATEMENT             |                    |    34 |  1496 |    3

  6 |

  |   1 |  NESTED LOOPS                |                    |    34 |  1496 |    3

  6 |

  |   2 |   INDEX RANGE SCAN           | PK_USER_TO_CHANNEL |    34 |   272 |

  2 |

  |   3 |   TABLE ACCESS BY INDEX ROWID| PUB_CHANNEL        |     1 |    36 |

  1 |

  |   4 |    INDEX UNIQUE SCAN         | PK_CHANNEL         |     1 |       |

  0 |

  --------------------------------------------------------------------------------

  ---

  Note

  -----

  - 'PLAN_TABLE' is old version

  Statistics

  ----------------------------------------------------------

  1  recursive calls

  0  db block gets

  77  consistent gets

  0  physical reads

  0  redo size

  2273  bytes sent via SQL*Net to client

  514  bytes received via SQL*Net from client

  4  SQL*Net roundtrips to/from client

  0  sorts (memory)

  0  sorts (disk)

  33  rows processed

  SQL>

  结论:还是由于sql的质量比较差导致的逻辑读比较多。

  此时的逻辑读=consistent gets+db block gets=77

  感慨:原因虽然找到了,在一个线上系统查找该sql很困难,总之在一个线上系统做点调整真难


« 
» 
快速导航

Copyright © 2016 phpStudy | 豫ICP备2021030365号-3