应用优化

创建索引必须考虑的问题
1 使用索引扫描和全表扫描分别需要读取多少个块?
2 对给定表最常用的查询条件的列组合是什么?
这可以通过查询v$sqlarea或v$sqltext,查看执行次数较多的SQL语句。
3 创建索引时给定列的选择性
一般按照选择性降序排列索引列
4 在SQL语句的WHERE短语中所有列都必须包括在索引中吗?
不用。包括空值的列以及选择性低的列应该排除在索引列之外。
5 表是基于事务的还是基于查询的?
对经常更新的表,必须将多余的索引删除。
6 表被更新的方式,是批量更新还是在线事务型?
决定是否要删除索引或使之无效

复合索引与单列索引的有效性
一般而言,如果一个索引有多列,建立一个多列的复合索引要比建多个单列索引有效。

何时重建索引?
alter index index_name validate structure;
然后查询index_stats的height字段,如果变化较大可能需要重建索引。

重建一个大索引考虑的问题
并行创建和nologging选项

如:alter index index_name rebuild
    parallel (degree 4)
    nologging
    tablespace xxx;

在书写SQL时应该考虑到的与索引有关的问题
何时使用索引,何时不使用索引,见以下示例:
表line_items有1000000条记录
索引列为shipped_date
数据在shipped_date列上的分布十分分散
索引列的选择性高
注意:这里最关键的是列shipped_date在表中的数据非常分散,查询时要访问到大部分的数据块,因此这里要用全表扫描
select /*+ FULL(LINE_ITEMS) PARALLEL(LINE_ITEMS,2) */ *
  from line_items
 where shipped_date between sysdate
   and (sysdate-30);

表ORDERSe 100000行
列ord_id可以包括字母和数字并且以大写保存,但应用程序允许小写输入
建有复合索引ord_id,ord_status,ord_date
索引的选择性很好
正确的写法是:
select *
  from orders
where ord_id=upper(':b1') /*此处不应该写成upper(ord_id)=':b1'*/
  and ord_status = 'not filled'
  and ord_date = sysdate;

注意数据类型的匹配,这可能会导致索引的正常使用;如列类型为varchar2,则赋值时一定要加引号

如果要使用索引,就不要使用null操作符

注意绑定变量的使用

避免在循环中重复使用单个的insert,update,delete操作,尽可能批量操作
如下例:
before:
declare
   ord_struct orders%rowtype;
   cursor c_ord is
     select *
       from orders
     where ord_status='not filled'
       and ord_date= sysdate;
begin 
open c_ord;
loop
    fetch c_ord into ord_struct;
    exit when c_ord%notfound;

    insert into temp_ord values (ord_struct.ord_id,ord_struct.ord_date,(ord_struct.ord_price*1.1),ord_struct.ord_status);

    commit;
end loop;
close c_ord;
end;
/

after:
begin
  insert /*+ APPEND */ into temp_ord
  select ord_id,ord_date,(ord_price*1.1),ord_status from orders
  where ord_status='Not filled'
    and ord_date=sysdate;
  commit;
end;
/

不要在子查询中关联父表,这是一个CPU密集型的操作,如:
before:
select outer.*
  from emp outer
 where outer.salary >
   (select avg(salary)
      from emp inner
     where inner.dept_id=outer.dept_id);

after:
select e1.*
 from emp e1, (select e2.dept_id dept_id, avg(e2.salary) avg_sal from emp e2
               group by dept_id) dept_avg_sal
 where e1.dept_id=dept_avg_sal.dept_id
 and e1.dalary>dept_avg_sal.avg_sal;

SQL优化时注
1 当使用索引效率不高时,全表扫描通常有效;
2 当SQL包含子查询时,先优化子查询。如果可以用表连接来代替子查询,先尝试用表连接来实现。
3 使用not exists来代替not in.
4 使用like ‘A%’操作来代替substr函数
5 当合适的时候使用nvl函数来避免偶然的类型转换。另外,NVL函数的效率比||操作要高点
6 对使用OR的复杂查询,考虑使用union all来进行拆分;
7 使用最有效的索引
8 create indexes on foreign key columns if the queries always retrieve master-detail relationship-based rows
9  按选择性降序排列创建复合索引
10 使用非唯一索引来支持唯一索引。如,如果ORDERS表需要在ord_id上创建一个主键约束,如果有另一个复合索引并以ord_id为先导列,则不需要再建立一个独立的唯一索引。
11 对低基数列并对这些列进行or,and 或not 操作时,在列上建立位图索引。如果表上有频繁的并发DML操作,则不应该考虑使用位图索引。
11 对相对静态表,并且查询其中一定范围内的数据,考虑用单表hash或者索引cluster。
12 尽量避免在复杂SQL中使用视图
13 尽量避免远程访问。
14 批量集合操作时选择数组(array)
15 考虑动量sql的使用
16 对大表考虑使用表和索引分区
17 创建索引时,可以考虑在session级修改sort_area_size为一个较大值以尽量减少磁盘排序,加快创建速度。

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

转载于:http://blog.itpub.net/9375/viewspace-609261/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值