ORACLE学习笔记性能优化3

9.怎么避免使用特定索引
  在很多时候,Oracle会错误的使用索引而导致效率的明显下降,我们可以使用一点点技巧而避免使用不该使用的索引,如:
  表test,有字段a,b,c,d,在a,b,c上建立联合索引inx_a(a,b,c),在b上单独建立了一个索引Inx_b(b)。

  在正常情况下,where a=? and b=? and c=?会用到索引inx_a,where b=?会用到索引inx_b,但是,where a=? and b=? and c=? group by b会用到哪个索引呢?在分析数据不正确(很长时间没有分析)或根本没有分析数据的情况下,oracle往往会使用索引inx_b。通过执行计划的分析,这个索引的使用,将大大耗费查询时间。

  当然,我们可以通过如下的技巧避免使用inx_b,而使用inx_a。

  where a=? and b=? and c=? group by b||'' --如果b是字符
  where a=? and b=? and c=? group by b+0 --如果b是数字

  通过这样简单的改变,往往可以是查询时间提交很多倍
  当然,我们也可以使用no_index提示,相信很多人没有用过,也是一个不错的方法:
  select /*+ no_index(t,inx_b) */ * from test t
  where a=? and b=? and c=? group by b

  举例:
  本来在CM_USER上有索引IDX_CM_USER4(ACC_ID)和IDX_CM_USER8(BILL_ID),可是执行如下语句的时候很慢。
  select * from CM_USER where  acc_id =1200007175
  and user_status>0 and bill_id like '13%' order by acc_id,bill_id

  用explain分析,发现执行计划是用IDX_CM_USER8.如下查询
  select * from user_indexes where table_name ='CM_USER' 发现IDX_CM_USER8没有分析过。

  用下面语句执行计划改变
  select /*+INDEX(CM_USER IDX_CM_USER4)*/* from CM_USER where  acc_id =1200007175 and user_status>0 and bill_id like '13%' order by acc_id,bill_id

  或者分析索引
  exec dbms_stats.gather_index_stats(ownname => 'QACS1',indname => 'IDX_CM_USER8',estimate_percent => 5 );
  可以发现执行计划恢复正常。


10.Oracle什么时候会使用跳跃式索引扫描
  这是9i的一个新特性跳跃式索引扫描(Index Skip Scan).
  例如表有索引index(a,b,c),当查询条件为where b=?的时候,可能会使用到索引index(a,b,c),如,执行计划中出现如下计划:
  INDEX (SKIP SCAN) OF 'TEST_IDX' (NON-UNIQUE)

  Oracle的优化器(这里指的是CBO)能对查询应用Index Skip Scans至少要有几个条件:
  <1> 优化器认为是合适的。
  <2> 索引中的前导列的唯一值的数量能满足一定的条件(如重复值很多)。
  <3> 优化器要知道前导列的值分布(通过分析/统计表得到)。
  <4> 合适的SQL语句
  等。


11.怎么样创建使用虚拟索引
  可以使用nosegment选项,如
  create index virtual_index_name on table_name(col_name) nosegment;

  如果在哪个session需要测试虚拟索引,可以利用隐含参数来处理
  alter session set "_use_nosegment_indexes" = true;

  就可以利用explain plan for select ……来看虚拟索引的效果,利用@$ORACLE_HOME/rdbms/admin/utlxpls查看执行计划,最后,根据需要,我们可以删除虚拟索引,如普通索引一样
  drop index virtual_index_name;

  注意:虚拟索引并不是物理存在的,所以虚拟索引并不等同于物理索引,不要用自动跟踪去测试虚拟索引,因为那是实际执行的效果,是用不到虚拟索引的。

12.怎样监控无用的索引
  Oracle 9i以上,可以监控索引的使用情况,如果一段时间内没有使用的索引,一般就是无用的索引
  语法为:
  开始监控:alter index index_name monitoring usage;
  检查使用状态:select * from v$object_usage;
  停止监控:alter index index_name nomonitoring usage;

  当然,如果想监控整个用户下的索引,可以采用如下的脚本:
  set heading off
  set echo off
  set feedback off
  set pages 10000
  spool start_index_monitor.sql
  SELECT 'alter index '||owner||'.'||index_name||' monitoring usage;'
  FROM dba_indexes
  WHERE owner = USER;
  spool off
  set heading on
  set echo on
  set feedback on
  ------------------------------------------------
  set heading off
  set echo off
  set feedback off
  set pages 10000
  spool stop_index_monitor.sql
  SELECT 'alter index '||owner||'.'||index_name||' nomonitoring usage;'
  FROM dba_indexes
  WHERE owner = USER;
  spool off
  set heading on
  set echo on
  set feedback on

原文地址:https://www.cnblogs.com/einyboy/p/2493520.html