oracle性能優化(項目中的一個sql優化的簡單記錄)

在項目中,寫的sql主要以查詢爲主,可是數據量一大,就會突出sql性能優化的重要性。其實在數據量2000W之內,能夠考慮索引,但超過2000W了,就要考慮分庫分表這些了。本文主要記錄在實際項目中,一個須要查詢很慢的sql的優化過程,若是有更好的方案,請在下面留言交流。sql

不少文章都有關於sql優化的方法,這裏就不一一陳述了。若是有須要能夠查看博客:https://blog.csdn.net/linhaiyun_ytdx/article/details/79101122性能優化

 

SELECT T.YHBH,
       (SELECT NAME FROM DIM_REGION WHERE CODE = SUBSTR(T.GDDWBM, 0, 4)) GDDWMC,
       (SELECT NAME FROM DIM_REGION WHERE CODE = T.GDDWBM) FJMC,
       T.DFNY,
       T.YHMC,
       T.YDDZ,
       (SELECT NAME FROM DIM_ELECTRICITY_TYPE WHERE CODE = T.YHLBDM) YDLBMC
  FROM (SELECT DISTINCT T.YHBH,
                        DECODE(T.GDDWBM,
                               NULL,
                               '0000',
                               DECODE(T.GDDWBM, '09', '0000', T.GDDWBM)) AS GDDWBM,
                        T.BBNY AS DFNY,
                        T.YHLBDM AS YHLBDM,
                        T.YHMC,
                        T2.YDDZ
          FROM V_TEMP_TABLE_JHCBHSTJ_HISTORY T, TMP_KH_YDKH T2
         WHERE T.YHBH = T2.YHBH(+)
           AND NOT EXISTS (SELECT 1
                  FROM DJHJSL_LSB_FZ_HISTORY B
                 WHERE B.BBNY = T.BBNY
                   AND B.YHBH = T.YHBH
                   AND B.GDDWBM = T.GDDWBM
                   AND B.YHLBDM = T.YHLBDM
                   AND B.ZDCBZHS <> '0')
) T 
WHERE SUBSTR(T.GDDWBM, 0, 4) = '0946' 
  AND T.DFNY = '201911'

這個是個人sql腳本。其實這個腳本一點都不復雜。其中V_TEMP_TABLE_JHCBHSTJ_HISTORYDJHJSL_LSB_FZ_HISTORY每月增長330萬,目前有1960多萬, TMP_KH_YDKH表有330多萬。DIM_REGION DIM_ELECTRICITY_TYPE 是兩個數據字典項表。oracle

在沒有索引的狀況下,這個腳本執行須要30s,看到執行過程,如今都是全表掃描的。接下來開始優化。工具

1.修改腳本的查詢,將外層的查詢條件放到裏面,減小數據量。性能

SELECT T.YHBH,
       (SELECT NAME FROM DIM_REGION WHERE CODE = SUBSTR(T.GDDWBM, 0, 4)) GDDWMC,
       (SELECT NAME FROM DIM_REGION WHERE CODE = T.GDDWBM) FJMC,
       T.DFNY,
       T.YHMC,
       T.YDDZ,
       (SELECT NAME FROM DIM_ELECTRICITY_TYPE WHERE CODE = T.YHLBDM) YDLBMC
  FROM (SELECT DISTINCT T.YHBH,
                        DECODE(T.GDDWBM,
                               NULL,
                               '0000',
                               DECODE(T.GDDWBM, '09', '0000', T.GDDWBM)) AS GDDWBM,
                        T.BBNY AS DFNY,
                        T.YHLBDM AS YHLBDM,
                        T.YHMC,
                        T2.YDDZ
          FROM V_TEMP_TABLE_JHCBHSTJ_HISTORY T, TMP_KH_YDKH T2
         WHERE T.YHBH = T2.YHBH(+)
           AND NOT EXISTS (SELECT 1
                  FROM DJHJSL_LSB_FZ_HISTORY B
                 WHERE B.BBNY = T.BBNY
                   AND B.YHBH = T.YHBH
                   AND B.GDDWBM = T.GDDWBM
                   AND B.YHLBDM = T.YHLBDM
                   AND B.ZDCBZHS <> '0')
            AND SUBSTR(T.GDDWBM, 0, 4) = '0946' 
            AND T.BBNY = '201911'
) T 

2.對三個表都建上索引測試

V_TEMP_TABLE_JHCBHSTJ_HISTORY根據DFNYSUBSTR(T.GDDWBM, 0, 4)建上聯合索引。大數據

CREATE INDEX IDX_TMP_JHCBHSTJ_HISTORY_UNION ON V_TEMP_TABLE_JHCBHSTJ_HISTORY(BBNY,SUBSTR(GDDWBM, 0, 4));

TMP_KH_YDKH表,使用了關聯,因此須要對yhbh建個索引優化

create index IDX_YHBH_KH on TMP_KH_YDKH (YHBH);

對於DJHJSL_LSB_FZ_HISTORY表,在not EXISTS裏面,會全表掃描這個表,如今對他創建聯合索引試試。spa

CREATE INDEX IDX_DJHJSL_FZ_HISTORY_UNION ON V_TEMP_TABLE_JHCBHSTJ_HISTORY(BBNY,YHBH,GDDWBM,YHLBDM);

查看oracle的執行計劃,創建聯合索引,並無讓這個表走索引,仍是在全表掃描的,可是查詢已經提高到9s了。.net

接下來對分別對這四個字段創建索引:

create index IDX_DJHJSL_FZ_HISTORY_BBNY on DJHJSL_LSB_FZ_HISTORY (BBNY);
create index IDX_DJHJSL_FZ_HISTORY_YHBH on DJHJSL_LSB_FZ_HISTORY (YHBH);
create index IDX_DJHJSL_FZ_HISTORY_GDDWBM on DJHJSL_LSB_FZ_HISTORY (GDDWBM);
create index IDX_DJHJSL_FZ_HISTORY_YHLBDM on DJHJSL_LSB_FZ_HISTORY (YHLBDM);

 從執行計劃來看,oracle只走了IDX_DJHJSL_FZ_HISTORY_BBNY這個索引,如今最快已經到1.95s了。

雖然如今已經知足了查詢3s內的要求,可是考慮到之後,每月的數據增加,數據量有5000萬,一億這樣的大數據量的時候仍是會很慢。

其實我在正式環境測試的時候,NOT EXISTS 裏面的這個表,創建單個索引是沒有用的,創建聯合索引纔會使這個表走索引,多是由於電腦的cpu不一樣等因素影響的。

 

上面的優化方法固然不能知足項目的需求,接下來結合業務進行優化。做爲一個監控系統,數據是T+1的,不須要追求實時性,這些數據,都是使用etl抽取工具天天定時抽取的。並且每月300萬數據,用戶只關注的只有幾千條。因此結合業務,咱們在使用etl抽取完數據後,將用戶關注的數據插入到另外一張表中,這樣,每月只有幾千條數據,這樣的話,一年也才幾萬條數據,對oracle來講決定是零壓力的。

 

若是你們還有其餘的方式優化,請在下方留言交流。

相關文章
相關標籤/搜索