關聯表更新Merge優化

昨天,有一位美女提出瞭如下需求,週末沒事,在家裏好好查了一下。

1 需求分析

有三張表,商品表(TBLITEM),庫存表(TBLSTORAGE),庫存管理表(TBLMANAGEMENT);

每一種商品對應的處理區分是0,並且庫存總量大於1000,就把庫存管理表的庫存區分更新爲1,小於1000,更新爲0。

2 數據準備

DROP TABLE TBLITEM;

DROP TABLE TBLSTORAGE;

DROP TABLE TBLMANAGEMENT;

create table TBLITEM as  select d.OWNER as ITEMNO,round(dbms_random.value) as HANDLE_FLG from dba_objects d WHERE d.owner<>'sys';

create table TBLSTORAGE as select d.OWNER as ITEMNO,trunc(dbms_random.value(0,100)) as STROR_AMOUNT from dba_objects d WHERE d.owner<>'sys' ;

create table TBLMANAGEMENT as select d.OWNER as ITEMNO,round(dbms_random.value) as STORE_KIND from dba_objects d WHERE d.owner<>'sys' ;

3 SQL改善

3.1 寫法一

UPDATE TBLMANAGEMENT M

SET M.STORE_KIND=(SELECT CASE WHEN SUM(S.STROR_AMOUNT)>1000 THEN 1

                         ELSE 0 END

                  FROM TBLITEM I

                                INNER JOIN TBLSTORAGE S

                                     ON I.ITEMNO=S.ITEMNO

                              WHERE I.HANDLE_FLG=0

                                AND M.ITEMNO=I.ITEMNO

                                   AND M.ITEMNO=S.ITEMNO

                              GROUP BY S.ITEMNO)

WHERE EXISTS (SELECT 1

              FROM TBLITEM I

                            INNER JOIN TBLSTORAGE S

                              ON I.ITEMNO=S.ITEMNO

                        WHERE I.HANDLE_FLG=0

                          AND M.ITEMNO=I.ITEMNO

                             AND M.ITEMNO=S.ITEMNO);

這種寫法能夠實現需求,但是作爲資深的老牌強迫症患者,一條SQL語句中重複掃描一張表是不能忍受的,所以有了下面異想天開的寫法。

 

3.2寫法二(錯誤)

WITH TMP AS

    (SELECT S.ITEMNO, (CASE WHEN SUM(S.STROR_AMOUNT)>1000 THEN 1

                       ELSE 0 END) AS AMOUTFLG

     FROM TBLITEM I

           INNER JOIN TBLSTORAGE S

                 ON I.ITEMNO=S.ITEMNO

        WHERE I.HANDLE_FLG=0

        GROUP BY S.ITEMNO)

UPDATE TBLMANAGEMENT M

SET M.STORE_KIND=(SELECT T.AMOUTFLG

                  FROM TMP T

                              WHERE T.ITEMNO=M.ITEMNO)

WHERE EXISTS(SELECT 1

             FROM TMP T

                      WHERE T.ITEMNO=M.ITEMNO);

這條語句直接有語法錯誤,如果是檢索處理,用with提取公共部分,還可以,但是是更新操作,無法實現。

3.3 Merge優化

MERGE INTO TBLMANAGEMENT M

  USING (SELECT S.ITEMNO, (CASE WHEN SUM(S.STROR_AMOUNT)>1000 THEN 1

                          ELSE 0 END) AS AMOUNT_FLG

         FROM TBLITEM I

                     INNER JOIN TBLSTORAGE S

                            ON I.ITEMNO=S.ITEMNO

               WHERE I.HANDLE_FLG=0

               GROUP BY S.ITEMNO) T

    ON (M.ITEMNO=T.ITEMNO)

WHEN MATCHED THEN UPDATE SET M.STORE_KIND=T.AMOUNT_FLG;

用merge改寫,避免了表的重複的掃描,物理讀有181k降低到75多。IO減少一半。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章