性能瓶頸在函數的亂用。原代碼黃色部分。ide
12分鐘->35秒函數
---------------------------------------------------------------------------------------------性能
1.對兩個函數調用屢次,並且兩個函數之間還有調用關係。(優化器是能夠自動把函數體拆出來,拼到主查詢裏面一塊兒優化的。可是太複雜了它也蒙。)優化
IsSpecial和gettradedate函數都是從1010表拿數據。spa
IsSpecial 掃2次1010表code
Gettradedate 掃1次1010表orm
而4603表有25萬多數據,對這個查詢用了2次IsSpecial 和3次 Gettradedate,最糟糕的狀況對1010表的掃描次數大約25萬*(2+3) =125萬次索引
用with把1010邏輯提出來,而後經過cross join鏈接到主查詢,只掃一次。ci
2.這個案例跟昨天那個代碼結構類似,可是狀況正好相反。element
若是把or改爲union,性能反而會變慢。(昨天的把or改爲union性能會變快)
開始判斷性能瓶頸的時候發生了點悲劇。4603表有25萬的數據,惟一性索引在OB_OBJECT_ID上面(錯當作在f1_4603上了,o(╯□╰)o),而咱們須要的只有2500左右,並且與1090相連用的是f1_4603.
因此錯認爲了走4603的索引效率會變高。
其實這個案例,無論索引在OB_OBJECT_ID仍是f1_4603上面都沒有用。由於真正把數據從25萬篩選成2500的條件是在f3_4603上面,而f3上面沒有索引,因此必須全表掃描。
因此,若是把or改爲了union,原本對4603表的全掃描只掃1次,就會變成2次,效率反而下降。(昨天的案例把or改成union,從1次全表掃描變爲2次索引掃描,效率提高)。
3.其餘類似子查詢,可按以前的辦法合併。
-------------------------------優化後代碼----------------------------------------------
with td as
(select max(f1_1010) - min(f1_1010) special,
max(f1_1010) ed,
min(f1_1010) sd
from (select f1_1010
from wind.tb_object_1010
where f1_1010 < to_char(&PlanTime, 'yyyymmdd')
order by f1_1010 desc)
where rownum <= 2)
select *
from (Select case
when f16_1090 like '%!%' then
substr(f16_1090, 1, instr(f16_1090, '!') - 1)
else
F16_1090
end Zqdm,
case
when nvl(F6_4603, 0) = 0 then
nvl(F4_4603, 0)
else
nvl(F6_4603, 0)
end Net_value,
0 Begin_Net,
case
when nvl(f4_4603, 0) <> 0 then
nvl(nvl(F5_4603, f4_4603), 0)
when nvl(f4_4603, 0) = 0 then
nvl(F5_4603, 0)
end Total_net,
---除貨幣基金累計未公佈時,取單位淨值[20140507]
0 Adjust_net,
0 Adjust_Int,
Case
When exists (select '1'
from wind.tb_object_1101
where f14_1101 = f2_1090
and f13_1101 = f3_4603
and f15_1101 = 1) Then
'Y'
Else
'N'
End div_date,
F3_4603 data_date,
Case
When Exists (Select '1'
From Wind.tb_object_4521
Where f1_4521 = f16_1090
And f14_4521 = F3_4603) Then
(Select f9_4521
From Wind.tb_object_4521
Where f1_4521 = f16_1090
And f14_4521 = F3_4603)
When f5_1090 = '上海' Then
'H'
When f5_1090 = '深圳' Then
'S'
Else
'Y'
End market,
Case
When Exists (Select '1'
From Wind.tb_object_4521
Where f1_4521 = f16_1090
And f14_4521 = F3_4603) Then
(Select f15_4521
From Wind.tb_object_4521
Where f1_4521 = f16_1090
And f14_4521 = F3_4603)
ELSE
F100_1099
END fund_type,
(select (F5_1115 * 10000)
from wind.tb_object_1115 a
where f1_1115 = f2_1090
and a.f2_1115 = (Select Max(b.F2_1115)
From wind.tb_object_1115 b
Where a.f1_1115 = b.f1_1115
And b.f2_1115 <= F3_4603)) Total_amt,
Null As BataValue
From wind.tb_object_1090
inner join wind.tb_object_4603 b
on F1_4603 = f2_1090
inner join wind.tb_object_1099
on f1_1099 = F2_1090
cross join td
Where (f19_1090 = '0' or f18_1090 >= to_char(&PlanTime, 'yyyymmdd'))
and ((td.special = 1 and td.ed = F3_4603) or
(td.special != 1 and F3_4603 > td.sd and F3_4603 <= td.ed)))
where length(zqdm) <= 6
union all
Select case
when f16_1090 = 'TZ0001' then
'TZ0002'
when f16_1090 = 'TZ0002' then
'TZ0001'
---小寫轉大寫---
elSe
UPPER(f16_1090)
end Zqdm,
nvl(F3_4141, 0) Net_value,
0 Begin_Net,
case
when exists (select '1'
from wind.tb_object_1744
where f1_1744 = f1_4141
and f6_1744 = '貨幣市場型') then
0
else
nvl(nvl(F4_4141, F3_4141), 0)
end Total_net,
0 Adjust_net,
0 Adjust_Int,
'N' div_date,
f2_4141 data_date,
'Y' market,
nvl((select case
when f6_1744 = '貨幣市場型' then
'貨幣型'
else
f6_1744
end
from wind.tb_object_1744
where f1_1744 = f1_4141
and f6_1744 < > 'FOF'),
'債券型') fund_type,
nvl((Select f7_1772
From wind.tb_object_1772 b
Where f1_1772 = f2_1090
And f2_1772 = (Select Max(f2_1772)
From wind.tb_object_1772
Where b.f1_1772 = f1_1772)),
0) Total_amt,
null BataValue
From wind.tb_object_1090, wind.tb_object_4141 a
Where f1_4141 = f2_1090
And f2_4141 = (Select Max(f1_0012)
From wind.tb_object_0012
Where f1_0012 < to_char(&PlanTime, 'yyyymmdd')
And f3_0012 = 'CN'
And f4_0012 = 1
And F2_0012 = 'SSE')
AND F4_1090 = 'LC'
union
Select F16_1090 Zqdm,
nvl(F4_1449, 0) Net_value,
1 Begin_Net,
0 Total_net,
0 Adjust_net,
0 Adjust_Int,
'N' div_date,
F2_1449 data_date,
Case
When f5_1090 = '上海' Then
'H'
When f5_1090 = '深圳' Then
'S'
Else
'Y'
End market,
case
when exists (select '1'
from wind.tb_object_1400
where f2_1400 = f2_1090
and f6_1400 = '1'
and f3_1400 = '2001010503') then
'QDII'
else
(select decode(F100_1099, '貨幣市場型', '貨幣型', f100_1099)
from wind.tb_object_1099
where f1_1099 = f2_1090)
end fund_type,
(select F5_1115 * 10000
from wind.tb_object_1115 b
where f1_1115 = f2_1090
And b.f2_1115 = (Select Max(F2_1115)
From wind.tb_object_1115
Where f1_1115 = f2_1090
And f2_1115 < = f6_1449)) Total_amt,
(SELECT F4_5052
FROM WIND.TB_OBJECT_5052
WHERE F3_5052 = '613007000'
AND F1_5052 = F2_1090
AND F2_5052 =
(SELECT MAX(F2_5052)
FROM WIND.TB_OBJECT_5052
WHERE F1_5052 = F2_1090
AND F3_5052 = '613007000'
AND F2_5052 <= TO_CHAR(&PlanTime, 'YYYYMMDD'))) BataValue
From wind.tb_object_1090, wind.tb_object_1449 a
Where F1_1449 = f2_1090
And f19_1090 = '0'
and length(f16_1090) < = 6
and F3_1449 =
(select max(F16_1101)
from wind.tb_object_1101
where F16_1101 <= to_char(&PlanTime, 'yyyymmdd'))
AND NOT EXISTS (SELECT '1 '
from WIND.TB_OBJECT_4603
WHERE F3_4603 = F2_1449
AND F1_4603 = F1_1449)
------------------------原代碼-------------------------------------------------------------
函數1:
create or replace function wind.GetTradeDate(p_start varchar2,p_inc number) return varchar2 is
Result varchar2(10);
begin
if p_start is null then
return null;
end if;
if p_inc<0 then
select min(f1_1010) into Result
from (select f1_1010 from wind.tb_object_1010
where f1_1010<p_start order by f1_1010 desc)
where rownum<=abs(p_inc);
elsif p_inc>0 then
select max(f1_1010) into Result
from (select f1_1010 from wind.tb_object_1010
where f1_1010>p_start order by f1_1010)
where rownum<=abs(p_inc);
else
Result:=p_start;
end if;
return(Result);
end GetTradeDate;
函數2:
create