热门标签 | HotTags
当前位置:  开发笔记 > 数据库 > 正文

OracleSQL优化之使用索引提示一例-mysql教程

下午做完其他的就打算优化一下这个SQL首先查看这个SQL的执行计划在PLSQLDeveloper中的执行计划窗口中执行这个SQL然后得到执行计

下午做完其他的就打算优化一下这个SQL首先查看这个SQL的执行计划在PL/SQL Developer中的执行计划窗口中执行这个SQL然后得到执行计

在做数据库的安检时候,发现一个ORA-01555错误:

Oracle

这个SQL语句明显运行了很长时间而没有完成。在观察Statspack报告中这个SQL也在top
SQL中占用了大量的db cache。物理读很大。

Oracle

下午做完其他的就打算优化一下这个SQL
首先查看这个SQL的执行计划
在PL/SQL Developer中的执行计划窗口中执行这个SQL然后得到执行计划:如下

Oracle

可以看到在嵌套查询中使用了 提示 /*+ all_rows*/ (这个是我的错,因为在上礼拜五的时候我发现一条同样差不多的语句嵌套语句和另外一条语句是一模一样的,我使用了这个 /*+ all_rows*/提示优化了一下,开发人员觉得第一张图中中的语句也应该加上该提示,结果在今天这条语句出现了问题。)
Person表走的是索引全扫描这个效率有点儿低,但是更糟糕的是mailsend表走的是全表扫描,根据语句中的条件
select * from mailsend ms where ms.persOnid=p.userid and (sysdate-15)<=ms.senddate and ms.mailid=1102
从执行计划可以看出次查询并没有使用索引,在去到 dba_indexs 中查询mailsend表是否有索引
Select * from dba_indexs I where i.table_name=’MAILSEND’
果然没有索引。
于是乎创建一条索引:
Create index idx_perid_mailsend on mailsend(personid);
同时分析了一下该表
Analyzed table mailsend compute statistics;
改SQL中还是用了 in 这个关键字,在查询中最好将in使用exists替代来提高性能
修改后的sql如下:

Oracle

在看一下执行计划:

Oracle

这个时候解决了mailsend表的全表扫描情况,但是person表最外层还是走的全表扫描(虽然内层走的是主键索引扫描)这才是很重要的原因,update因为要更新内层的结果集,所以走的是全表扫描,没有使用索引,,显然是很慢的原因。
这个时候查看person的相关索引,只有两个复合索引。
这时候想起了可以使用提示强制走索引执行于是添加了一个索引提示 /*+ INDEX (tablename indexname) */(语法)
修改结果如下:
update /*+ INDEX ( per INDEX3_PERSON) */ person per
set per.sort = nvl(per.sort, 0) + 1
where exists
(select userid
from (select
p.userid, p.email
from Person p
where (sysdate - p.lastupdate) >=
(p.lastupdate + 3 - p.lastupdate)
and p.status = 3
and p.sort != 3
and not exists (select *
from mailsend ms
where ms.persOnid= p.userid
and (sysdate - 15) <= ms.senddate
and ms.mailid = 1102)) us where us.userid=per.userid)

再来看看执行计划:

Oracle

IO耗费降低到66。
本文完。

linux

推荐阅读
author-avatar
汽车时尚宠
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有