今天一同事发邮件说,有个sql,第一次跑的很快,后面跑的很慢,要我优化下,由于没有权限,不能查看oracle的数据字典(坑爹)执行计划也看不了,于是只有从sql,方面来着手(不看执行计划也能优化?具体咨询骚落和教主),不扯淡了,来看sql。
Select *
From (Select Distinct x.Bar_Code As Barcode,
x.Instance_Id As Processinstanceid,
x.Code As Processcode,
x.Priority As Priority,
z.Ati_Atdname As Nodename,
z.Wki_User As Userid,
To_Char(z.Wki_Createtime, 'yyyy-mm-dd hh24:mi:ss') As Arrivetime,
Ati_Endtime
From (Select Distinct x.*
From (Select a.Bar_Code
From f_Loan_Info a
Where a.Apply_Date >=
to_date('2010-05-25 00:00:00',
'yyyy-mm-dd hh24:mi:ss')
And a.Apply_Date <=
to_date('2015-05-25 23:59:59',
'yyyy-mm-dd hh24:mi:ss')
And a.Apply_City = '02'
And a.Apply_Channal In
(Select Paid
From Pa_Simpleness_Mode
Where Patable = 'PA_SALES_CHANNAL'
And Pastate = 1)
And (a.Follow_Branch In
(Select Branchcode
From Pa_Branch
Where Pastate = 1
And BrAnchcode = '0298') Or
a.Audit_Branch In
(Select Branchcode
From pa_Branch
Where Pastate = 1
And Branchcode = '0298') Or
a.Lending_Branch In
(Select Branchcode
From Pa_Branch
Where Pastate = 1 And Branchcode = '0298'))
And a.Apply_Loan_Product In
(Select DistiNct Paproductcode
From Pa_Loan_Pro_c
Where Pastate = 1
And Pa_CoMpany_c = '02')
Union
Select b.Bar_Code
From f_Scan_Loan_Track b
Where b.Oper_Time >=
to_date('2010-05-25 00:00:00',
'yyyy-mm-dd hh24:mi:ss')
And b.Oper_Time <=
to_date('2015-05-25 23:59:59',
'yyyy-mm-dd hh24:mi:ss')
And b.Applicant_City = '02'
And b.Channal In
(Select Paid
From Pa_Simpleness_Mode
Where Patable = 'PA_SALES_CHANNAL'
And Pastate = 1)
And b.Follow_Branch In
(SeLect Branchcode From Pa_Branch Where
Pastate = 1 And Branchcode = '0298')
And b.Loan_Product In
(Select Distinct Paproductcode FrOm Pa_Loan_Pro_c Where Pastate = 1 And Pa_Company_c = '02')
And Not Exists
(Select Bar_Code
From f_Loan_Info
Where Bar_Code = b.bAr_Code)
Union
Select c.Bar_Code
From f_App_Loan_Track c
Where c.Create_Date >=
to_date('2010-05-25 00:00:00',
'yyyy-mm-dd hh24:mi:ss')
And c.Create_Date <=
to_date('2015-05-25 23:59:59',
'yyyy-mm-dd hh24:mi:ss')
And c.Applicant_City = '02'
And 'KF' In (Select Paid
From Pa_Simpleness_Mode
Where Patable = 'PA_SALES_CHANNAL'
And Pastate = 1)
And c.Follow_Branch In
(Select BrancHcode
From Pa_Branch
Where Pastate = 1
And Branchcode = '0298')
And c.Loan_Product In
(Select Distinct Paproductcode
From Pa_Loan_Pro_c
Where Pastate = 1
And Pa_Company_c = '02')
And Not Exists
(Select Bar_Code
From f_Loan_Info
Where Bar_Code = c.Bar_Code)) t,
Uaf_Flow_Track x
Where t.Bar_Code = x.Bar_Code
And x.Loanstate = 'RJ') x
Left Join (Select a.Ati_Priid,
a.Ati_Atdname,
b.Wki_User,
b.Wki_Createtime,
a.Ati_Endtime
From Sunflow.Actiinstance a LeFt
Join Sunflow.Workitem b
On a.Ati_Priid = b.Wki_Priid
And a.Ati_Id = b.Wki_Atiid
Where a.Ati_Id In
(Select Max(Ati_Id)
From SunFlow.Actiinstance
Where Ati_Priid = a.Ati_Priid)) z
On x.Instance_Id = z.Ati_Priid)
Order By Barcode Desc
这个sql总体来看,并不复杂,就是x表和z表关联,由于不能看执行计划,就把x表和z表单独拿出来跑一下,发现z表跑的有点慢,于是就把以前的sql改写成下面这样了。
Select *
From (Select Distinct x.Bar_Code As Barcode,
x.Instance_Id As Processinstanceid,
x.Code As Processcode,
x.Priority As Priority,
z.Ati_Atdname As Nodename,
z.Wki_User As Userid,
To_Char(z.Wki_Createtime, 'yyyy-mm-dd hh24:mi:ss') As Arrivetime,
Ati_Endtime
From (Select Distinct x.*
From (Select a.Bar_Code
From f_Loan_Info a
Where a.Apply_Date >=
To_Date('2010-05-25 00:00:00',
'yyyy-mm-dd hh24:mi:ss')
And a.Apply_Date <=
To_Date('2015-05-25 23:59:59',
'yyyy-mm-dd hh24:mi:ss')
And a.Apply_City = '02'
And a.Apply_Channal In
(Select Paid
From Pa_Simpleness_Mode
Where Patable = 'PA_SALES_CHANNAL'
And Pastate = 1)
And (a.Follow_Branch In
(Select Branchcode
From Pa_Branch
Where Pastate = 1
And Branchcode = '0298') Or
a.Audit_Branch In
(Select Branchcode
From Pa_Branch
Where Pastate = 1
And Branchcode = '0298') Or
a.Lending_Branch In
(Select Branchcode
From Pa_Branch
Where Pastate = 1
And Branchcode = '0298'))
And a.Apply_Loan_Product In
(Select Distinct Paproductcode
From Pa_Loan_Pro_c
Where Pastate = 1
And Pa_Company_c = '02')
Union
Select b.Bar_Code
From f_Scan_Loan_Track b
Where b.Oper_Time >=
To_Date('2010-05-25 00:00:00',
'yyyy-mm-dd hh24:mi:ss')
And b.Oper_Time <=
To_Date('2015-05-25 23:59:59',
'yyyy-mm-dd hh24:mi:ss')
And b.Applicant_City = '02'
And b.Channal In
(Select Paid
From Pa_Simpleness_Mode
Where Patable = 'PA_SALES_CHANNAL'
And Pastate = 1)
And b.Follow_Branch In
(Select Branchcode
From Pa_Branch
Where Pastate = 1
And Branchcode = '0298')
And b.Loan_Product In
(Select Distinct Paproductcode
From Pa_Loan_Pro_c
Where Pastate = 1
And Pa_Company_c = '02')
And Not Exists
(Select Bar_Code
From f_Loan_Info
Where Bar_Code = b.Bar_Code)
Union
Select c.Bar_Code
From f_App_Loan_Track c
Where c.Create_Date >=
To_Date('2010-05-25 00:00:00',
'yyyy-mm-dd hh24:mi:ss')
And c.Create_Date <=
To_Date('2015-05-25 23:59:59',
'yyyy-mm-dd hh24:mi:ss')
And c.Applicant_City = '02'
And 'KF' In (Select Paid
From Pa_Simpleness_Mode
Where Patable = 'PA_SALES_CHANNAL'
And Pastate = 1)
And c.Follow_Branch In
(Select Branchcode
From Pa_Branch
Where Pastate = 1
And Branchcode = '0298')
And c.Loan_Product In
(Select Distinct Paproductcode
From Pa_Loan_Pro_c
Where Pastate = 1
And Pa_Company_c = '02')
And Not Exists
(Select Bar_Code
From f_Loan_Info
Where Bar_Code = c.Bar_Code)) t,
Uaf_Flow_Track x
Where t.Bar_Code = x.Bar_Code
And x.Loanstate = 'RJ') x
Left Join (Select Ati_Priid,
Ati_Atdname,
Wki_User,
Wki_Createtime,
Ati_Endtime
From (Select a.Ati_Priid,
a.Ati_Atdname,
b.Wki_User,
b.Wki_Createtime,
a.Ati_Endtime,
Row_Number() Over(Partition By Ati_Priid Order By Ati_Id Desc) Rn
From Sunflow.Actiinstance a
Left Join Sunflow.Workitem b
On a.Ati_Priid = b.Wki_Priid
And a.Ati_Id = b.Wki_Atiid)
Where Rn = 1) z
On x.Instance_Id = z.Ati_Priid)
Order By Barcode Desc
这个sql拿到库里面跑,每次都是不到1s,没有出现以前的问题,那么问题算是解决了。
由于本着研究的精神,为什么第一个sql,会出现第一次跑很快,后面跑的很慢,经过研究发现是oracle11gR2新特效feedback的bug(8521689)
Cardinality Feedback基数反馈是版本11.2(11.2.0.1及以后)中引入的关于SQL 性能优化的新特性,该特性主要针对 统计信息陈旧、无直方图或虽然有直方图但仍基数计算不准确的情况,Cardinality基数的计算直接影响到后续的JOIN COST等重要的成本计算评估,造成CBO选择不当的执行计划。以上是Cardinality Feedback特性引入的初衷。
在普通用户下,在sys用户下是会发生feedback特性
1,没有收集表的统计信息,并且dynamic samping也没有开启
2,查询条件复杂(比如条件有函数)或者涉及多列,但是没有收集扩展统计信息(extend statics)
统计信息中有:
hint : opt_param(‘_optimizer_use_feedback’ ‘false’)
修改参数: alter system set “_optimizer_use_feedback”=false scope=both;
hint:cardinality(test, 1)强制使用
查看share pool中还有那些sql用到了feedback
select sql_ID,USE_FEEDBACK_STATS FROM V$SQL_SHARED_CURSOR where USE_FEEDBACK_STATS =’Y’;