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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

MySQL not exists 真的不走索引么?

發(fā)布時(shí)間:2025/3/21 数据库 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL not exists 真的不走索引么? 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在一些業(yè)務(wù)場(chǎng)景中,會(huì)使用NOT EXISTS語句確保返回?cái)?shù)據(jù)不存在于特定集合,部分同事會(huì)發(fā)現(xiàn)NOT EXISTS有些場(chǎng)景性能較差,甚至有些網(wǎng)上謠言說”NOT EXISTS不走索引”,哪對(duì)于NOT EXISTS語句,我們?nèi)绾蝺?yōu)化呢?

以今天優(yōu)化的SQL為例,優(yōu)化前SQL為:

SELECT?count(1)? FROM?t_monitor?m? WHERE?NOT?exists?(SELECT?1?FROM?t_alarm_realtime?AS?a?WHERE?a.resource_id=m.resource_id?AND?a.resource_type=m.resource_type?AND?a.monitor_name=m.monitor_name )

我們使用LEFT JOIN方式進(jìn)行優(yōu)化,優(yōu)化后SQL為:

SELECT?count(1)? FROM?t_monitor?m? LEFT?JOIN?t_alarm_realtime?AS?a?ON?a.resource_id=m.resource_id?AND?a.resource_type=m.resource_type?AND?a.monitor_name=m.monitor_name? WHERE?a.resource_id?is?NULL

優(yōu)化效果:

優(yōu)化前執(zhí)行時(shí)間29秒以上,優(yōu)化后1.2秒,優(yōu)化提升25倍。

NOT EXISTS真的不走索引么?

查看兩種SQL的執(zhí)行計(jì)劃!

使用NOT EXIST方式的執(zhí)行計(jì)劃:

使用LEFT JOIN方式的執(zhí)行計(jì)劃:

從執(zhí)行計(jì)劃來看,兩個(gè)表都使用了索引,區(qū)別在于NOT EXISTS使用“DEPENDENT SUBQUERY”方式,而LEFT JOIN使用普通表關(guān)聯(lián)的方式。

推薦看下:為什么索引能提高查詢速度?

通過MySQL提供的Profiling方式來查看兩種方式的執(zhí)行過程。

使用NOT EXIST方式的執(zhí)行過程:

使用LEFT JOIN方式的執(zhí)行過程:

從執(zhí)行過程來看,LEFT JOIN方式的主要消耗在Sending data一項(xiàng)上(1.2s),而NOT EXISTS方式主要消耗在executeing和Sending data兩項(xiàng)上,受限于Profiling只存放100行記錄緣故。

從Profiling中只能看到47個(gè)” executeing和Sending data”的組合項(xiàng)(每個(gè)組合項(xiàng)約50us),通過執(zhí)行計(jì)劃看出,外表t_monitor的數(shù)據(jù)量為578436行,忽略統(tǒng)計(jì)信息不準(zhǔn)情況下,使用NOT EXISTS方式應(yīng)該會(huì)產(chǎn)生578436個(gè)” executeing和Sending data”的組合項(xiàng),總計(jì)消耗時(shí)間=50μs*578436=28921800us=28.92s。

從上面執(zhí)行過程可以推斷出:

使用NOT EXISTS方式的執(zhí)行性能嚴(yán)重依賴于NOT EXISTS子查詢的執(zhí)行次數(shù)即外層查詢結(jié)果集的數(shù)據(jù)量。

  • 當(dāng)外層查詢結(jié)果集的數(shù)據(jù)量N較小時(shí)執(zhí)行性能較好,如有N=10執(zhí)行時(shí)間為50μs*10=500us=0.005s,再加上一些額外消耗,執(zhí)行結(jié)果也能在0.01秒或10毫秒內(nèi)范圍,這個(gè)響應(yīng)時(shí)間應(yīng)該能被大部分應(yīng)用程序接受。

  • 當(dāng)外層程勛結(jié)果集的數(shù)據(jù)量N較大甚至上千萬數(shù)據(jù)量時(shí),NOT EXISTS的查詢性能會(huì)變得非常糟糕,甚至?xí)罅肯姆?wù)器IO和CPU資源從而影響其他業(yè)務(wù)正常運(yùn)行。

  • 除上述問題外,在優(yōu)化過程中發(fā)現(xiàn)本應(yīng)該存儲(chǔ)相同數(shù)據(jù)的resource_id列在兩個(gè)表中定義不同,一表為VARCHAR而另外一表為BIGINT,外部結(jié)果集的字段類型和NOT EXIST字表中字段類型不同導(dǎo)致NOT EXISTS子查詢中無法使用索引,使得子查詢性能較差,最終影響整個(gè)查詢的執(zhí)行性能。

    京東商城也曾出現(xiàn)過大量類似案例,一些表使用VARCHAR來存放訂單號(hào),而另一些表使用BIGINT來存放,在兩表進(jìn)行管理時(shí)性能極差,希望研發(fā)同事引以為戒。

    版權(quán)聲明:本文為博主原創(chuàng)文章,遵循?CC 4.0 BY-SA?版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接和本聲明。本文鏈接:https://blog.csdn.net/guanfengliang1988/article/details/92814376

    總結(jié)

    以上是生活随笔為你收集整理的MySQL not exists 真的不走索引么?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。