中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

兩則數據庫優化的分析與解決是怎樣的

發布時間:2021-12-02 09:48:24 來源:億速云 閱讀:97 作者:柒染 欄目:大數據

兩則數據庫優化的分析與解決是怎樣的,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

No matter who or what, you will not destroy me. If you knock me down, I'll get back up. If you beat me, I will rise and try again.

本來昨天就答應顧問查看,財務軟件中的一個存在的問題,但一直在忙沒有時間來支持,今天一大早就找了顧問,問題出現在 ORACLE 數據庫,在執行一個存儲過程時,第一次返回的速度很快,而第二次后續的就會越來越慢,最后可能都無法忍受了。

首先就的先看看到底是怎樣的一個存儲過程,經過查看后,發現是兩個存儲過程,其中一個是一個游標,并且每次將獲取到的數值變量給另一個存儲過程,進行調用,并且另一個調用的存儲過程,另一個存儲過程存在兩個游標,屬于嵌套型的。

首先這里面最主要的一個SQL 是這樣的

insert into cntvoucher_wqt

    (vchdate, kmh, opkmh, dir, vchmemo, mny, mccode, vtid)

    select cnt.vchdate,

           cnt.kmh,

           cnt.opkmh,

           cnt.dir,

           cnt.vchmemo,

           sum(cnt.mny) mny,

           cpid,

           vtid_id

      from cntvoucher cnt

      left join cntbusssheet sheet

        on cnt.transid = sheet.sheetid

     where cnt.vchdate = f_actdate

          --and sheet.extaddr2 in

       and exists (select distinct b.extaddr2

              from cntvoucher a

              left join cntbusssheet b on a.transid = b.sheetid

              where sheet.extaddr2 = b.extaddr2

               and a.cpid = f_eventcode

               and a.kmh = f_km

               and a.dir = f_dir

               and a.vchdate = f_actdate

            -- and a.vchdate>=date'2018-01-01'

            )

     group by cnt.vchdate, cnt.kmh, cnt.opkmh, cnt.dir, cnt.vchmemo, cpid;

經過存儲過程的運行,發現鎖存在于

INSERT INTO CNTVOUCHER_WQT (VCHDATE, KMH, OPKMH, DIR, VCHMEMO, MNY, MCCODE, VTID) 

SELECT CNT.VCHDATE, CNT.KMH, CNT.OPKMH, CNT.DIR, CNT.VCHMEMO, SUM(CNT.MNY) MNY, CPID, :B2 

FROM CNTVOUCHER CNT 

LEFT JOIN CNTBUSSSHEET SHEET ON CNT.TRANSID = SHEET.SHEETID WHERE CNT.VCHDATE = :B1 AND 

EXISTS (SELECT DISTINCT B.EXTADDR2 

        FROM CNTVOUCHER A 

        LEFT JOIN CNTBUSSSHEET B ON A.TRANSID = B.SHEETID 

        WHERE SHEET.EXTADDR2 = B.EXTADDR2 AND A.CPID = :B5 AND A.KMH = :B4 

        AND A.DIR = :B3 AND A.VCHDATE = :B1 ) 

        GROUP BY CNT.VCHDATE, CNT.KMH, CNT.OPKMH, CNT.DIR, CNT.VCHMEMO, CPID

以上的語句。

通過查看EXPLAIN 并驗證這個 select 語句的執行時間,這個語句大約執行的時間在 不到一分鐘,由于內存小,數據量也比較大幾千萬的數據(其實還好)。

而其實我之前是有講過的,在數據的操作中,(SQL SERVER , MYSQL , PG, Oracle),這幾類RDS 數據庫都最好都不要使用(尤其查詢很慢)的insert into  select 。

我們建議的方法是,查詢和插入要分開,并且ORACLE  SQL SERVER ,PG都有良好的臨時表機制,尤其是SESSION 基別的。 MYSQL 也是有臨時表的,但大概率是不使用的,這與他使用方式有關,當然要使用看具體情況。

而上面的出現問題的兩個原因

1  使用游標,的方式觸發 insert into  select , 相當于高頻的觸發這個查詢較慢的SQL 語句,并且 INSERT INTO 和 SELECT 相當一個事務,則插入的表就會被鎖,所以造成經常出現無法忍受的慢的問題,尤其是循環的次數很多的情況下。

數據庫的優化中,是希望能批次一次性處理的,就不要分多次處理(例如游標方式),而在MYSQL 中的思想,短而小的事務,其實放到其他數據庫的使用中也是有益處的。終歸長期霸占表的 X鎖,這絕對是不美好的。

這里給出的解決方法

1 采用 ORACLE 的臨時表 SESSION級別的,那每次將數據先插入臨時表,然后在將臨時表的數據 insert  into  到最終的表中,這樣降低insert into  select 的時間,對數據庫優化是有幫助的。

2 理順邏輯,能將游標轉換為一次 select 能查詢的數據,就不要使用游標的方式。

當然還有其他的優化方式,但目前的情況,以上兩種可以解決問題。

剛理清上面的問題,下午開發人員又過來

提出需求,是這樣的,批量要插入MYSQL 的數據,插入的表是有唯一索引的,而當插入的值與這個唯一索引有沖突的時候,則不能插入,這是當然的,是當初設計這個唯一索引的根本,就是不要他插入,防止扣款或放款重復,但問題是如果批量插入,一條插不進去,整體都ROLLBACK ,這可不是一件不美好的事情,而后期程序員改為一條條的數據插入,那其實是一件更不美好的事情,低效,對數據庫的壓力明顯增高。

最后的解決方案:

insert into  on duplicate key update  這樣的語句,既然批量的插入中發現有重復的,我們可以在原表增加一個字段,并且發現重復的值,我們就不在插入,并且更新后面的那個新添加的字段,去UPDATE 一個值。這樣既保證有重復插入不批量回滾,同時也能知道到底哪些行,曾經有重復的值妄圖想插入。算是一個一舉兩得的idea。

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

余江县| 庄浪县| 河北区| 博兴县| 息烽县| 泰来县| 青神县| 开江县| 广丰县| 曲阳县| 宁德市| 夹江县| 喀喇沁旗| 洪湖市| 朔州市| 泸水县| 达日县| 社会| 松阳县| 孝感市| 会泽县| 汶川县| 德格县| 禹州市| 莲花县| 阿鲁科尔沁旗| 永春县| 会宁县| 察隅县| 九江县| 马边| 图木舒克市| 德阳市| 上高县| 大埔区| 洮南市| 静宁县| 德清县| 岑溪市| 伊宁市| 沂源县|