exists是對外表作loop迴圈,每次loop迴圈再對內表進行查詢,在專案中遇到類似的問題,資料量大時,not exists不管用並且執行sql的時間很長,
在網上查了一些資料,所以記錄下來:
原始sql:
explain select relation.id,relation.invited_code,relation.uid,relation.create_time,relation.invited_uid from tran_user_invited_relation relation,
tran_user user where 1=1 and user.uid=relation.uid and user.register_time>='2017-01-01 19:40:09' and user.register_time<='2017-12-15 16:33:49' and
not exists (select 1 from tran_user_reward reward where reward.sources='invite_auth' and reward.invited_relation_id=relation.id)
關於優化把以上sql修改一下做幾點思考:
對於原始語句,因為是not exists判斷,所以子查詢中沒有必要select * from dual,只需select id甚至是select 1都可以。
另外,鑑於mysql子查詢演算法效能較差,考慮改寫成對應的join方式,因為這裡是not exist判斷,所以改寫時有一定技巧,
即可使用左連線,然後過濾出未能連線的記錄做乙個條件篩選得到想要的資料。還有,原始語句最外層的查詢也是select 至於這個是否有必要應當依據具體業務,
盡量在滿足業務要求的條件下取盡可能少的字段。最後,即時做了上述優化,若在連線條件上沒有合適的索引sql效能仍然會非常差(特別是在表的資料量巨大的時候),
所以考慮在連線的條件列reward.invited_relation_id和relation.id上分別建立索引。
優化後的sql是:
sql由原來的30s的執行時間減少到1-2左右秒內。
explain select invited.id,invited.invited_code,invited.uid,invited.create_time,invited.invited_uid from (
(select user.uid from tran_user user where 1=1 and user.rna_status=1 and user.register_time>='2017-01-01 19:40:09'
and user.register_time<='2017-12-15 16:33:49') as `user` left join
(select invited.id,invited.invited_code,invited.uid,invited.create_time,invited.invited_uid from
tran_user_invited_relation invited) as invited on user.uid=invited.uid left join
(select id as rewards_id ,invited_relation_id from tran_user_reward where 1=1 and sources='invite_auth' and invited_relation_id !=0) reward on
invited.id=reward.invited_relation_id ) where reward.rewards_id is null and invited.id is not null
MySQL not exists 真的不走索引麼
在一些業務場景中,會使用not exists語句確保返回資料不存在於特定集合,部分同事會發現not exists有些場景效能較差,甚至有些網上謠言說 not exists不走索引 哪對於not exists語句,我們如何優化呢?以今天優化的sql為例,優化前sql為 select count 1 f...
spark調優 shuffle調優
基於spark1.6 引數可以通過 new sparkcontext set 來設定,也可以通過命令的引數設定 conf spark.shuffle.file.buffer 預設值 32k 引數說明 該引數用於設定shuffle write task的bufferedoutputstream的buf...
Spark Spark調優 資源調優
spark在乙個executor的記憶體分為三塊,1.一塊是execution記憶體 2.一塊是storge 記憶體 3.一塊是其他記憶體 執行記憶體是執行記憶體,加入,聚合都是在這部分記憶體中執行.shuffle的資料也會先快取在這個記憶體中,滿了再寫入磁碟,能減少io,其實地圖過程也是在這個記憶...