SQL優化(exist和notexist優化爲join提速30s)

前段時間上線一個項目,後面因爲查詢超時直接不顯示數據,在測試環境是沒有問題的,也是因爲在測試環境數據量原因沒什麼異常,當時因爲考慮不周也沒有想到測試和生產的區別。

第一個SQL:

 SELECT
     OWNER .*
    FROM
     OWNER .T_OWNER_INFO OWNER
    WHERE
     OWNER .STATUS = '1'
    AND EXISTS (
     SELECT
      1
     FROM
      house.T_STOREGROUP_SCOPE_NEW SCOPE
     WHERE
      SCOPE .SCOPE_TYPE = '1'
     AND SCOPE .BUILDING_ID = OWNER .BUILDING_ID
     UNION
      SELECT
       1
      FROM
       house.T_STOREGROUP_SCOPE_HOUSE SCOPEH
      WHERE
       SCOPEH.SCOPE_TYPE = '1'
      AND SCOPEH.HOUSE_ID = OWNER .HDIC_HOUSE_ID
    )

執行時間大概20多秒

優化後:

SELECT
     OWNER .*
    FROM
     OWNER .T_OWNER_INFO OWNER
     join (
     SELECT
     distinct
      -1 house_id,SCOPE.BUILDING_ID
     FROM
      house.T_STOREGROUP_SCOPE_NEW SCOPE
     WHERE
      SCOPE .SCOPE_TYPE = '1'
     UNION all
      SELECT
      distinct
       SCOPEH.HOUSE_ID,SCOPEH.BUILDING_ID
      FROM
       house.T_STOREGROUP_SCOPE_HOUSE SCOPEH
      WHERE
       SCOPEH.SCOPE_TYPE = '1'
    ) sh on (sh.house_id = owner.HDIC_HOUSE_ID and sh.building_id = owner.building_id) or (sh.building_id=owner.building_id and sh.house_id = -1)
    WHERE
     OWNER .STATUS = '1'

執行時間3s

第二個SQL:

SELECT
     OWNER .*
    FROM
     OWNER .T_OWNER_INFO OWNER
    WHERE
     OWNER .STATUS = '1'
    AND EXISTS (
     SELECT
      1
     FROM
      house.T_STOREGROUP_SCOPE_NEW SCOPE
     WHERE
      SCOPE .SCOPE_TYPE = '2'
     AND SCOPE .BUILDING_ID = OWNER .BUILDING_ID
     UNION
      SELECT
       1
      FROM
       house.T_STOREGROUP_SCOPE_HOUSE SCOPEH
      WHERE
       SCOPEH.SCOPE_TYPE = '2'
      AND SCOPEH.HOUSE_ID = OWNER .HDIC_HOUSE_ID
    )
    AND NOT EXISTS (
     SELECT
      1
     FROM
      house.T_STOREGROUP_SCOPE_NEW SCOPE
     WHERE
      SCOPE .SCOPE_TYPE = '1'
     AND SCOPE .BUILDING_ID = OWNER .BUILDING_ID
     UNION
      SELECT
       1
      FROM
       house.T_STOREGROUP_SCOPE_HOUSE SCOPEH
      WHERE
       SCOPEH.SCOPE_TYPE = '1'
      AND SCOPEH.HOUSE_ID = OWNER .HDIC_HOUSE_ID
    )

執行時間:30s

優化後:

 SELECT
     OWNER .*
    FROM
     OWNER .T_OWNER_INFO OWNER
     join 
     (SELECT
      -1 house_id,SCOPE.BUILDING_ID building_id
     FROM
      house.T_STOREGROUP_SCOPE_NEW SCOPE
      group by -1, SCOPE.BUILDING_ID having wm_concat(distinct SCOPE.SCOPE_TYPE)='2'
     UNION all
      SELECT
       SCOPEH.house_id,SCOPEH.BUILDING_ID
      FROM
       house.T_STOREGROUP_SCOPE_HOUSE SCOPEH
       group by scopeh.house_id,scopeh.building_id having wm_concat(distinct SCOPEH.SCOPE_TYPE)='2') sh 
       on (sh.house_id = owner.HDIC_HOUSE_ID and sh.building_id = owner.building_id) or (sh.building_id=owner.building_id and sh.house_id = -1)
    WHERE
     OWNER .STATUS = '1'

優化後時間大約3s

其實還是不夠快,所以又考慮了下索引,基本上關聯的幾個ID就是T_STOREGROUP_SCOPE_HOUSE的house_id和building_id,兩個建一個聯合索引

T_STOREGROUP_SCOPE_NEW的building_id建索引

T_OWNER_INFO的building_id建索引

最後速度下來是不到1s

 

總結:

通過這次自己覆盤,其實可以提前避免的。第一、每一個需求都需要提前考慮線上和生產的區別,或者其他方面全面考慮,思考各方面可能的影響來提前避免。第二、雖然APP沒有預生產、但是接口可以先在預生產測試的,通過postman接口測試來提前看下有什麼問題。第三、提高SQL水平,對於自己來說自己的SQL水平還有很大的提升空間,有時需要轉換自己的四路,修煉內功,多說無益~

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