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

歡迎訪問 生活随笔!

生活随笔

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

数据库

ORACLE使用WITH AS和HINT MATERIALIZE优化SQL解决FILTER效率低下

發布時間:2025/3/11 数据库 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ORACLE使用WITH AS和HINT MATERIALIZE优化SQL解决FILTER效率低下 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原文:http://blog.csdn.net/liangweiwei130/article/details/37882503

-------------------------------------------------

在做項目的過程中,一個頁面使用類似如下的SQL查詢數據,為了保密和使用方便,我把項目中有關的表名和字段替換使用ORACLE數據庫中的系統表和字段。

在我所做的項目中,類似ALL_TABLES的表中大概有8W多條數據,下面這個查詢SQL很慢。


[sql]?view plain?copy ?print?
  • WITH?PARAMS?AS??
  • ?(SELECT?''?USER_ID,?''?SDATE,?'%'?||?''?||?'%'?SNAME?FROM?DUAL)??
  • SELECT?AU.USERNAME,?AU.USER_ID??
  • ??FROM?ALL_USERS?AU??
  • ?INNER?JOIN?PARAMS?PA??
  • ????ON?1?=?1??
  • ?INNER?JOIN?DBA_USERS?DU??
  • ????ON?AU.USERNAME?=?DU.USERNAME??
  • ?WHERE?((PA.SDATE?IS?NULL?AND?PA.USER_ID?IS?NOT?NULL?AND??
  • ???????AU.USER_ID?=?PA.USER_ID)?OR??
  • ?????????
  • ???????(PA.SDATE?IS?NULL?AND?PA.USER_ID?IS?NULL?AND??
  • ???????AU.USERNAME?NOT?IN??
  • ???????(SELECT?AU.USERNAME??
  • ????????????FROM?ALL_USERS?AU??
  • ???????????INNER?JOIN?DBA_USERS?DEV??
  • ??????????????ON?AU.USERNAME?=?DEV.USERNAME??
  • ???????????INNER?JOIN?(SELECT?OWNER?AS?USERNAME??
  • ????????????????????????FROM?ALL_TABLES?T??
  • ???????????????????????WHERE?T.LAST_ANALYZED?=?TRUNC(SYSDATE))?ATA??
  • ??????????????ON?AU.USERNAME?=?ATA.USERNAME))?OR??
  • ???????(PA.SDATE?IS?NOT?NULL?AND??
  • ???????AU.USERNAME?IN??
  • ???????(SELECT?AU.USERNAME??
  • ????????????FROM?ALL_USERS?AU??
  • ???????????INNER?JOIN?DBA_USERS?PA??
  • ??????????????ON?AU.USERNAME?=?PA.USERNAME??
  • ???????????INNER?JOIN?ALL_TABLES?ATA??
  • ??????????????ON?PA.USERNAME?=?ATA.OWNER??
  • ???????????WHERE?TO_CHAR(ATA.LAST_ANALYZED,?'YYYY-MM-DD')?=?PA.SDATE)?AND??
  • ???????AU.USER_ID?=?PA.USER_ID))??
  • ???AND?DU.PROFILE?LIKE?'D%'??
  • ???AND?AU.USERNAME?LIKE?PA.SNAME??
  • 針對上面的SQL語句執行慢的問題,我做了如下的分析:


    ????????????????第一步,把語句的WHERE條件后的三個OR都分別和主查詢一塊執行,執行速度都很快,放到一塊就很慢。


    ????????????????第二步,對比上面SQL和三個OR拆分出來的三個SQL的執行計劃,如下圖所示。發現上面SQL的執行中有一個FILTER,過濾器謂詞中用到了NOT EXISTS,是導致這條SQL跑的慢的原因。



    原因找到了,就得想辦法把執行計劃的FILTER去掉。開始想加HINT,但是實驗了很多HINT,都不起作用。最后的結果還一樣,后來想到WITH AS?能提高SQL的查詢速度,就把影響SQL執行的那段SQL放到WITH AS里面,結果還是一樣。后來嘗試把HINT?MATERIALIZEWITH AS?結合使用,修改成如下的SQL,查詢速度立即提升了很多。如下圖所示,執行計劃中FILTERNOT EXISTS不存在了。

    [sql]?view plain?copy ?print?
  • WITH?PARAMS?AS??
  • ?(SELECT?''?USER_ID,?''?SDATE,?'%'?||?''?||?'%'?SNAME?FROM?DUAL),??
  • USERNAMEDATA?AS??
  • ?(SELECT?/*+?materialize?*/??
  • ???AU.USERNAME??
  • ????FROM?ALL_USERS?AU??
  • ???INNER?JOIN?DBA_USERS?DEV??
  • ??????ON?AU.USERNAME?=?DEV.USERNAME??
  • ???INNER?JOIN?(SELECT?OWNER?AS?USERNAME??
  • ????????????????FROM?ALL_TABLES?T??
  • ???????????????WHERE?T.LAST_ANALYZED?=?TRUNC(SYSDATE))?ATA??
  • ??????ON?AU.USERNAME?=?ATA.USERNAME)??
  • SELECT?AU.USERNAME,?AU.USER_ID??
  • ??FROM?ALL_USERS?AU??
  • ?INNER?JOIN?PARAMS?PA??
  • ????ON?1?=?1??
  • ?INNER?JOIN?DBA_USERS?DU??
  • ????ON?AU.USERNAME?=?DU.USERNAME??
  • ?WHERE?((PA.SDATE?IS?NULL?AND?PA.USER_ID?IS?NOT?NULL?AND??
  • ???????AU.USER_ID?=?PA.USER_ID)?OR??
  • ?????????
  • ???????(PA.SDATE?IS?NULL?AND?PA.USER_ID?IS?NULL?AND??
  • ???????AU.USERNAME?NOT?IN?(SELECT?USERNAME?FROM?USERNAMEDATA))?OR??
  • ???????(PA.SDATE?IS?NOT?NULL?AND??
  • ???????AU.USERNAME?IN??
  • ???????(SELECT?AU.USERNAME??
  • ????????????FROM?ALL_USERS?AU??
  • ???????????INNER?JOIN?DBA_USERS?PA??
  • ??????????????ON?AU.USERNAME?=?PA.USERNAME??
  • ???????????INNER?JOIN?ALL_TABLES?ATA??
  • ??????????????ON?PA.USERNAME?=?ATA.OWNER??
  • ???????????WHERE?TO_CHAR(ATA.LAST_ANALYZED,?'YYYY-MM-DD')?=?PA.SDATE)?AND??
  • ???????AU.USER_ID?=?PA.USER_ID))??
  • ???AND?DU.PROFILE?LIKE?'D%'??
  • ???AND?AU.USERNAME?LIKE?PA.SNAME??

  • 總結:

    FILTER中,NOT EXISTS后的SQL語句多次執行,本來數據量就很大,每次都要執行一遍,結果可想而知。但是使用HINT?MATERIALIZEWITH AS?結合使用,把內聯視圖實體化,執行過程中會創建基于視圖的臨時表。這樣就不會每次NOT EXISTS都去執行一遍大數據表的掃描,只需要掃描一次即可。

    但是是不是可以在WITHAS中的每個語句都實體化那?如果WITH AS中的語句只被調用一次的話,最好還是不要使用HINT?MATERIALIZE,因為使用HINT?MATERIALIZE第一次查詢會創建基于視圖結果的臨時表,這也耗費一些時間。多次使用的話可以使用HINT?MATERIALIZE


    總結

    以上是生活随笔為你收集整理的ORACLE使用WITH AS和HINT MATERIALIZE优化SQL解决FILTER效率低下的全部內容,希望文章能夠幫你解決所遇到的問題。

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