共计 1914 个字符,预计需要花费 5 分钟才能阅读完成。
这篇文章主要介绍“Oracle SQL 执行计划异常的处理方法”,在日常操作中,相信很多人在 Oracle SQL 执行计划异常的处理方法问题上存在疑惑,丸趣 TV 小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Oracle SQL 执行计划异常的处理方法”的疑惑有所帮助!接下来,请跟着丸趣 TV 小编一起来学习吧!
现象:
下面语句一直以来都比较高效,执行计划用了索引范围扫描后经历三次嵌套循环,可在 2 秒内返回结果,但今天经同事反映却走了 1 分多钟!
原 SQL 语句:
Select * From (Select Rownum As Rownumber__, t.*
From (Select T1.Orderdate As OrderDate ,
T1.Status As Status ,
T1.Ordercode As OrderCode ,
T1.Sumamt As SumAmt ,
T1.Ordertype As OrderType ,
T1.Questiondesc As QuestionDesc ,
T1.Ordersource As OrderSource ,
T2.Accepter As Accepter ,
T2.City As City ,
T1.Isquestion As IsQuestion ,
T1.Issplit As IsSplit ,
T1.Salemode As SaleMode ,
T1.Stockout As StockOut ,
T2.Encmobile As EncMobile ,
T2.Encphone As EncPhone ,
Decryptbykey(T2.Mobilephone) As MobilePhone ,
T2.Province As Province ,
T3.Checkercode As CheckerCode ,
T3.Iscancel As IsCancel ,
T3.Ischeck As IsCheck ,
T3.Isclose As IsClose ,
T3.Isfinish As IsFinish ,
T1.Ischange As IsChange
From Xs_Order T1 Join Xs_Orderpsaddress T2
On T1.Ordercode = T2.Ordercode Join Xs_Orderstatus T3
On T1.Ordercode = T3.Ordercode
Order By T1.Ordercode Desc) t
Where OrderDate = :Orderdate0 And StockOut = :Stockout1) Temp
Where Rownumber__ 0and Rownumber__ = 20
后来查看执行计划,执行计划变成:
分析:
由于后面两个表是大表,全表扫描导致大量的 IO 消耗,该语句采用了绑定变量,如果把绑定变量调整为常量后,执行计划正常走了索引连接,执行后返回也是在 2 秒内。曾经以为是绑定变量窥探异常问题,后来把表的统计信息重新更新后,问题依旧,接着运行 SQL TUNNING 包,概要只建议说要启用并行,但全表扫描并没有消除,考虑到代价太高就放弃,于是想用 DBMS_SPM 包来载入该语句:
BASELINE:
declare
l_pls number;
begin
l_pls := DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE(
sql_id= a0wawpy5hfrt3 ,
plan_hash_value = 2253704843, -- 注意这里的 2253704843 是我用常量带入后正常的 PLAN_HASH_VALUE
enabled = YES
end;
执行后,发现语句还是走了错误的执行计划,曾经考虑想用捕捉基线的方式进行演化,但由于该语句带绑定变量,会话级比较难搞,所以想到用包删除共享池里的该执行计划,让它重新进行硬解析:操作如下:
exec dbms_shared_pool.purge(0000000DE5E6B808,2332516131 , c)
–第一个参数为 v$sqlarea 中 address 和 hash_value,第二个为 cursor 类型 )
处理后执行计划重新产生,并自动应用了 2253704843 这个执行计划,查询效率正常:
到此,关于“Oracle SQL 执行计划异常的处理方法”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注丸趣 TV 网站,丸趣 TV 小编会继续努力为大家带来更多实用的文章!