SQL優(yōu)化INNER JOIN子查詢代替EXISTS

需求是將未分配的記錄纤泵,按照指定排序選一條分配給一個人骆姐。
最原始的實現(xiàn)是,查詢更新捏题,先加鎖逾礁,select出一條刻肄,再update颊郎,然后釋放鎖微渠,由于select很慢,還提前生成了緩存循狰,兩分鐘生成一次窟社。

經(jīng)過梳理,得到以下SQL绪钥,用的exists語法灿里,直接update,利用MySQL的鎖機制保證不會重復分配程腹。

UPDATE com_info c SET infoOperatorName='wy-test', infoOperatorFlag=1 
WHERE deleteFlag=0 AND infoType='F道路封閉' AND infoOperatorFlag=0 AND infoOperatorName='' 
AND EXISTS (SELECT 1 FROM ext_info e WHERE e.infoCode=c.infoCode AND e.infoCheckResult='有效') 
ORDER BY DATE(infoCreateTime) DESC, catagory_priority, city_priority, infoLevel DESC, infoCreateTime DESC LIMIT 1 ;

實測耗時4s左右匣吊,很穩(wěn)定。

一番優(yōu)化后寸潦,舍棄了exists色鸳,改用inner join + 子查詢,如下:

UPDATE com_info t1 INNER JOIN (
    SELECT c.infoCode FROM com_info c INNER JOIN ext_info e ON c.infoCode=e.infoCode  
    WHERE deleteFlag=0 AND infoType='F道路封閉' AND infoOperatorFlag=0 AND infoOperatorName='' 
    AND e.infoCheckResult='有效'
    ORDER BY DATE(infoCreateTime) DESC, catagory_priority, city_priority, infoLevel DESC, infoCreateTime DESC LIMIT 1
) t2 ON t1.infoCode=t2.infoCode SET infoOperatorName='wy-test', infoOperatorFlag=1;

實測耗時0.28s见转,很穩(wěn)定命雀。

以下是執(zhí)行情況和執(zhí)行計劃:


執(zhí)行耗時

執(zhí)行計劃

這里INNER JOINEXISTS快的原因,其實也看場景池户。
由于兩張表的規(guī)模是一樣的咏雌,并且主鍵相同,所以JOIN會走主鍵索引校焦,非成薅叮快。EXISTS反而會去遍歷了寨典。

掃描方式 type氛雪,從慢到快:

  1. all : 全表掃描
  2. index : 全索引掃描,和全表掃描一樣耸成。只是掃描表的時候按照索引次序進行而不是行报亩。主要優(yōu)點就是避免了排序, 但是開銷仍然非常大。如在Extra列看到Using index井氢,說明正在使用覆蓋索引弦追,只掃描索引的數(shù)據(jù),它比按索引次序全表掃描的開銷要小很多花竞。這個比all效率要好一點劲件,主要有幾種情況,一是當前的查詢是覆蓋索引的约急,即我們需要的數(shù)據(jù)在索引中就可以獲攘阍丁(Extra中有Using Index),或者是使用了索引進行排序厌蔽,這樣就避免數(shù)據(jù)的重排序(Extra中無 Using Index)牵辣。如果Extra中Using Index與Using Where同時出現(xiàn)的話,則是利用索引查找鍵值的意思
  3. range : 范圍查詢奴饮,避免了全索引掃描纬向,限制的范圍越小,效率越高
  4. index_subquery : 在 某 些 IN 查 詢 中 使 用 此 種 類 型 , 與 unique_subquery 類似,但是查詢的是非唯一 性索引
  5. unique_subquery : 在某些 IN 查詢中使用此種類型,而不是常規(guī)的 ref
  6. index_merge : 說明索引合并優(yōu)化被使用了
  7. ref_or_null : 如同 ref, 但是 MySQL 必須在初次查找的結(jié)果 里找出 null 條目,然后進行二次查找戴卜。
  8. ref : 使用了非唯一性索引進行數(shù)據(jù)的查找
  9. eq_ref : 使用的唯一性索引進行數(shù)據(jù)查找罢猪,例如主鍵索引之類的
  10. const : 通常情況下,將一個主鍵放置到where后面作為條件查詢叉瘩,mysql優(yōu)化器就能把這次查詢優(yōu)化轉(zhuǎn)化為一個常量膳帕,如何轉(zhuǎn)化以及何時轉(zhuǎn)化,這個取決于優(yōu)化器薇缅。這個比eq_ref效率高一點危彩。
  11. system : 表只有一行。不過這種情況下就沒意義了泳桦。
  12. NULL : MySQL不用訪問表或者索引就直接能到結(jié)果汤徽。

(關(guān)于覆蓋索引:MySQL系列-優(yōu)化之覆蓋索引

測試時發(fā)現(xiàn),由于com_info表的查詢需求很多灸撰,因此針對不同的場景谒府,對不同的字段建了各種索引拼坎,在測試數(shù)據(jù)庫和線上數(shù)據(jù)庫上測試發(fā)現(xiàn),不同的數(shù)據(jù)分布下完疫,MySQL對索引的選取差別很大泰鸡,線上庫采用了專門為這個場景建的聯(lián)合索引(包含了WHERE中需要的字段),而測試庫中則采用了index_merge的方式壳鹤,挨個索引走一遍盛龄,取交集,實測index_merge還是要比ref慢一兩個數(shù)量級芳誓。

另外index_merge在這個場景下會引發(fā)死鎖余舶。
因為這里用到了

UPDATE ... WHERE ... ORDER BY ... LIMIT ...;

由于有ORDER BY LIMIT存在,UPDARE的時候锹淌,會鎖住命中的所有行匿值。而index_merge在高并發(fā)的時候,如果索引行數(shù)有重疊赂摆,因為加鎖的順序可能不同千扔,互相等待可能會導致死鎖。加鎖順序的原因是库正,MySQL會先用索引1進行掃表曲楚,再用索引2進行掃表,然后求交集形成一個合并索引褥符。這個使用索引掃表的過程和我們本身SQL使用索引的順序可能存在互斥龙誊,造成了死鎖。

這里有個場景可能引發(fā)死鎖:
請求的WHERE條件不完全一樣喷楣,但包含了相同的某兩個字段趟大,可能造成上述的問題。

index_merge引發(fā)的死鎖排查

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末铣焊,一起剝皮案震驚了整個濱河市逊朽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌曲伊,老刑警劉巖叽讳,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異坟募,居然都是意外死亡岛蚤,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門懈糯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來涤妒,“玉大人,你說我怎么就攤上這事赚哗∷希” “怎么了硅堆?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長贿讹。 經(jīng)常有香客問我渐逃,道長,這世上最難降的妖魔是什么围详? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮祖屏,結(jié)果婚禮上助赞,老公的妹妹穿的比我還像新娘。我一直安慰自己袁勺,他們只是感情好雹食,可當我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著期丰,像睡著了一般群叶。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上钝荡,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天街立,我揣著相機與錄音,去河邊找鬼埠通。 笑死赎离,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的端辱。 我是一名探鬼主播梁剔,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼舞蔽!你這毒婦竟也來了荣病?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤渗柿,失蹤者是張志新(化名)和其女友劉穎个盆,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體朵栖,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡砾省,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了混槐。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片编兄。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖声登,靈堂內(nèi)的尸體忽然破棺而出狠鸳,到底是詐尸還是另有隱情揣苏,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布件舵,位于F島的核電站卸察,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏铅祸。R本人自食惡果不足惜坑质,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望临梗。 院中可真熱鬧涡扼,春花似錦、人聲如沸盟庞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽什猖。三九已至票彪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間不狮,已是汗流浹背降铸。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留摇零,地道東北人垮耳。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像遂黍,于是被迫代替她去往敵國和親终佛。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法雾家,類相關(guān)的語法铃彰,內(nèi)部類的語法,繼承相關(guān)的語法芯咧,異常的語法牙捉,線程的語...
    子非魚_t_閱讀 31,598評論 18 399
  • 寫在開頭 這里所說的劣質(zhì)SQL限定在數(shù)據(jù)量未到分庫分表和使用分布式緩存程度,指那些執(zhí)行較差的查詢敬飒、插入邪铲、更新、刪除...
    alivs閱讀 727評論 0 0
  • 有了孩子的人都會有這樣一個感觸无拗,“不是你教育孩子带到,而是孩子在教導你“,他們是天生的哲學家英染,生來就通曉一切的真理揽惹。 ...
    果蛋皮閱讀 756評論 3 2
  • 大腦如同肌肉被饿,如果長期不用的話,真的是會退化的搪搏。人類一旦停止了稍微有深度的思考狭握,面對問題的時候,就完全是憑著原始大...
    原同學閱讀 16,715評論 4 3
  • 我一直以為自己心靜如水 直到遇見他―― 一個逆著光行走的男孩 他驀然轉(zhuǎn)頭 笑了 有那么一瞬間我看呆了 但我并沒有以...
    仙女味的我閱讀 104評論 0 0