日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

Oracle某行系统SQL优化

發布時間:2024/8/26 windows 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Oracle某行系统SQL优化 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

問題說明:???

業務人員反饋系統跑批慢了,平時耗時5分鐘,現在需要跑3個多小時,而且是每月10日和每月15日都會變慢。

環境說明:

DB:Oracle?11.2.0.4.0?RAC OS:AIX?7.1

問題分析:

抓取跑批對應的慢SQL,查看SQL文本如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

select??'2021/08/15',

?????????RelativeDeductaccno,

?????????RelativeDeductaccno,

?????????LB.Deductaccno,

?????????lb.putoutno,

?????????LB.Customerid,

?????????LB.Customername,

?????????SI.ManageOrgID,

?????????0,

?????????LB.Normalbalance?+?LB.Overduebalance?+?LB.Waitoverduebalance?AS?balance,

?????????LB.Normalbalance?+?LB.Overduebalance?+?LB.Waitoverduebalance?AS?Actualbalance,

?????????SaveBeginSum?*?10000,

?????????LoanBeginSum?*?10000,

?????????SaveStandardSum?*?10000,

?????????LoanStandardSum?*?10000,

?????????nvl(ImpawnRatio1,?0),

?????????nvl(ImpawnRatio2,?0),

?????????nvl(ImpawnRatio3,?0),

?????????nvl(ImpawnRatio4,?0),

?????????IncomeBase?*?10000,

?????????LB.Executerate?/?(30?*?1000),

?????????LB.Loanrate?/?(30?*?1000),

?????????case

???????????when?LB.Executerate?<?LB.Loanrate?then

????????????LB.Executerate?/?(30?*?1000)

???????????else

????????????LB.Loanrate?/?(30?*?1000)

?????????end,

?????????SI.SaveRate?/?1000,

?????????LB.maturitydate,

?????????IncomeReturnDay,

?????????0,

?????????'0',

?????????'1',

?????????MainSaveToLoanFlag,

?????????case

???????????when?LB.LoanStatus?<=?'1'?then

????????????1

???????????else

????????????0

?????????end?as?LoanStatus,

?????????lb.assetflag,

?????????lb.businesstype,

?????????nvl(case

???????????????when?cjc_fun_xxxxxxx(LB.putoutno,?'2021/06/15')?>?0?then

????????????????cjc_fun_xxxxxxx(LB.putoutno,?'2021/06/15')

???????????????else

????????????????0

?????????????end,

?????????????0),

?????????case

???????????when?nvl(LB.assetflag,?0)?=?'1'?and

????????????????cjc_fun_xxxxxxx(LB.putoutno,?'2021/06/15')?>?0?then

????????????nvl(cjc_fun_xxxxxxx(LB.putoutno,?'2021/06/15'),?0)

???????????else

????????????0

?????????end

????from?cjcaaaaaaa_info?SI,?chen_balance?LB

???where?SI.putoutno?=?LB.putoutno

?????and?SI.Validdate?<=?'2021/08/15'

?????and?Status?=?'1'

?????and?ACCOUNTFLAG?=?'1'

手動執行,查看速度:

返回前100條記錄很快,之后平均每10秒取出100行數據,最終取出全部結果集耗時很長。

查看執行計劃:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

???PLAN_TABLE_OUTPUT

......

20?

21------------------------------------------------------------------------------------------------

22|?Id??|?Operation????????????????????|?Name????????????|?Rows??|?Bytes?|?Cost?(%CPU)|?Time?????|

23------------------------------------------------------------------------------------------------

24|???0?|?SELECT?STATEMENT?????????????|?????????????????|???????|???????|?14354?(100)|??????????|

25|???1?|??NESTED?LOOPS????????????????|?????????????????|??6966?|??1367K|?14354???(1)|?00:00:01?|

26|???2?|???NESTED?LOOPS???????????????|?????????????????|??6966?|??1367K|?14354???(1)|?00:00:01?|

27|*??3?|????TABLE?ACCESS?FULL?????????|?cjcaaaaaaa_info?|??6966?|???666K|???418???(1)|?00:00:01?|

28|*??4?|????INDEX?UNIQUE?SCAN?????????|?chen_balance_PK?|?????1?|???????|?????1???(0)|?00:00:01?|

29|???5?|???TABLE?ACCESS?BY?INDEX?ROWID|?chen_balance????|?????1?|???103?|?????2???(0)|?00:00:01?|

30------------------------------------------------------------------------------------------------

31?

32Predicate?Information?(identified?by?operation?id):

33---------------------------------------------------

34?

35???3?-?filter(("ACCOUNTFLAG"='1'?AND?"STATUS"='1'?AND?"SI"."VALIDDATE"<='2021/08/15'))

36???4?-?access("SI"."PUTOUTNO"="LB"."PUTOUTNO")

37

查看執行計劃,可以看到,即使cjcaaaaaaa_info走了全表掃描,cost也很低,預估的時間也很短。

難道是cjcaaaaaaa_info表統計信息不準確?

檢查后發現表統計信息是準確的,cjcaaaaaaa_info數據量很小。

cjcaaaaaaa_info和chen_balance表關聯關系很簡單,where謂詞條件也不復雜,那么是什么原因導致的SQL執行慢呢?

顯然當前的cjcaaaaaaa_info和chen_balance關聯采用NESTED LOOPS已經是最優的,嘗試添加hint強制hash join速度更慢了。

既然表關聯方式沒問題,表訪問路徑沒問題,還有可能哪塊有問題呢?

仔細檢查了SQL,發現查詢的列有一處?可疑的地方:

1

2

3

4

5

6

7

8

9

10

11

12

13

......

nvl(case

???????????????when?cjc_fun_xxxxxxx(LB.putoutno,?'2021/08/15')?>?0?then

????????????????cjc_fun_xxxxxxx(LB.putoutno,?'2021/08/15')

???????????????else

????????????????0

?????????????end,

?????????????0),

?????????case

???????????when?nvl(LB.assetflag,?0)?=?'1'?and

????????????????cjc_fun_xxxxxxx(LB.putoutno,?'2021/08/15')?>?0?then

????????????nvl(cjc_fun_xxxxxxx(LB.putoutno,?'2021/08/15'),?0)

......

此處的cjc_fun_xxxxxxx看上去像是一個function,查看function的定義:

select?dbms_metadata.get_ddl('FUNCTION','cjc_fun_xxxxxxx','CHENJ3')?from?dual;

函數部分由IF和ELSE兩部分組成,每部分包含多個SELECT查詢操作。

那么SQL執行慢,是否和cjc_fun_xxxxxxx函數有關呢?

注釋掉原SQL中包含cjc_fun_xxxxxxx函數部分,再次執行SQL,速度恢復正常,不超過5分鐘執行完成。

單獨進行函數部分測試:

單獨執行函數,速度很慢,每10秒返回100條記錄

1

2

3

4

5

6

7

8

9

10

11

12

select?case

?????????when?nvl(LB.assetflag,?0)?=?'https://www.fgba.net/'?and

??????????????cjc_fun_xxxxxxx(LB.putoutno,?'2021/08/15')?>?0?then

??????????nvl(cjc_fun_xxxxxxx(LB.putoutno,?'2021/08/15'),?0)

?????????else

??????????0

???????end

??from?cjcaaaaaaa_info?SI,?chen_balance?LB

?where?SI.putoutno?=?LB.putoutno

???and?SI.Validdate?<=?'2021/08/15'

???and?Status?=?'1'

???and?ACCOUNTFLAG?=?'1'

此時問題比較清晰了,就是因為cjc_fun_xxxxxxx函數部分導致SQL查詢速度慢,那么為什么只有每月10號和每月15日速度慢呢?

主要是因為原SQL包含case when部分,當每月10號和每月15日時,cjc_fun_xxxxxxx函數部分執行的次數更多。

cjc_fun_xxxxxxx函數對性能究竟有多大的影響?

在滿足sAssetFlag = '1'條件時,函數會執行8條select語句,并將結果集進行加和后返回。

在不滿足sAssetFlag = '1'條件時,函數會執行14條select語句,并將結果集進行加和后返回。

并且除了執行的select次數不同外,執行的select語句也是不一樣的,也就是在sAssetFlag值不同時,即使執行相同次數cjc_fun_xxxxxxx函數,執行時間也不同。

??綜合以上兩點,SQL執行時間取決于函數執行次數,和單次函數執行的邏輯有關。

例如:

在最極端的情況下,查詢的每條語句都會調用4次函數,每次函數執行14個select語句,在查詢60000條數據時,后臺實際會執行?336萬條select語句。

解決方案:

和業務人員溝通,cjc_fun_xxxxxxx函數不能在優化了,但是可以使用中間表代替。 例如,跑批前提前單獨執行cjc_fun_xxxxxxx函數部分,并將結果插入到臨時表t1中, 在跑批時,不需要在執行cjc_fun_xxxxxxx函數,直接和臨時表t1進行關聯即可, 經測試,速度有明顯改善,平均耗時不超過5分鐘。

總結

以上是生活随笔為你收集整理的Oracle某行系统SQL优化的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。