1. 程式人生 > >SQL優化案例--使用LEFT JOIN替換NOT EXISTS子查詢

SQL優化案例--使用LEFT JOIN替換NOT EXISTS子查詢

轉載

  在一些業務場景中,會使用NOT EXISTS語句確保返回資料不存在於特定集合,部分同事會發現NOT EXISTS有些場景效能較差,甚至有些網上謠言說”NOT EXISTS不走索引”,哪對於NOT EXISTS語句,我們如何優化呢?

##========================================================##

以今天優化的SQL為例,優化前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方式進行優化,優化後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

優化效果:

優化前執行時間29秒以上,優化後1.2秒,優化提升25倍

##========================================================##

哪NOT EXISTS真的不走索引麼?檢視兩種SQL的執行計劃:

使用NOT EXIST方式的執行計劃:

使用LEFT JOIN方式的執行計劃:

從執行計劃來看,兩個表都使用了索引,區別在於NOT EXISTS使用“DEPENDENT SUBQUERY”方式,而LEFT JOIN使用普通表關聯的方式。

##========================================================##

通過MySQL提供的Profiling方式來檢視兩種方式的執行過程

使用NOT EXIST方式的執行過程

使用LEFT JOIN方式的執行過程:

從執行過程來看,LEFT JOIN方式的主要消耗在Sending data一項上(1.2s),而NOT EXISTS方式主要消耗在executeing和Sending data兩項上,受限於Profiling只存放100行記錄緣故,從Profiling中只能看到47個” executeing和Sending data”的組合項(每個組合項約50us),通過執行計劃看出,外表t_monitor的資料量為578436行,忽略統計資訊不準情況下,使用NOT EXISTS方式應該會產生578436個” executeing和Sending data”的組合項,總計消耗時間=50μs*578436=28921800us=28.92s。

從上面執行過程可以推斷出:

使用NOT EXISTS方式的執行效能嚴重依賴於NOT EXISTS子查詢的執行次數即外層查詢結果集的資料量。

1、  當外層查詢結果集的資料量N較小時執行效能較好,如有N=10執行時間為50μs*10=500us=0.005s,再加上一些額外消耗,執行結果也能在0.01秒或10毫秒內範圍,這個響應時間應該能被大部分應用程式接受。

2、  當外層程勳結果集的資料量N較大甚至上千萬資料量時,NOT EXISTS的查詢效能會變得非常糟糕,甚至會大量消耗伺服器IO和CPU資源從而影響其他業務正常執行。

除上述問題外,在優化過程中發現本應該儲存相同資料的resource_id列在兩個表中定義不同,一表為VARCHAR而另外一表為BIGINT,外部結果集的欄位型別和NOT EXIST字表中欄位型別不同導致NOT EXISTS子查詢中無法使用索引,使得子查詢效能較差,最終影響整個查詢的執行效能


在一些業務場景中,會使用NOT EXISTS語句確保返回資料不存在於特定集合,部分同事會發現NOT EXISTS有些場景效能較差,甚至有些網上謠言說”NOT EXISTS不走索引,哪對於NOT EXISTS語句,我們如何優化呢?

##========================================================##

以今天優化的SQL為例,優化前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方式進行優化,優化後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

優化效果:

優化前執行時間29秒以上,優化後1.2秒,優化提升25

##========================================================##

NOT EXISTS真的不走索引麼?檢視兩種SQL的執行計劃:

使用NOT EXIST方式的執行計劃:

使用LEFT JOIN方式的執行計劃:

從執行計劃來看,兩個表都使用了索引,區別在於NOT EXISTS使用“DEPENDENT SUBQUERY”方式,而LEFT JOIN使用普通表關聯的方式。

##========================================================##

通過MySQL提供的Profiling方式來檢視兩種方式的執行過程

使用NOT EXIST方式的執行過程

使用LEFT JOIN方式的執行過程:

從執行過程來看,LEFT JOIN方式的主要消耗在Sending data一項上(1.2s),而NOT EXISTS方式主要消耗在executeingSending data兩項上,受限於Profiling只存放100行記錄緣故,從Profiling中只能看到47” executeingSending data”的組合項(每個組合項約50us),通過執行計劃看出,外表t_monitor的資料量為578436行,忽略統計資訊不準情況下,使用NOT EXISTS方式應該會產生578436” executeingSending data”的組合項,總計消耗時間=50μs*578436=28921800us=28.92s

從上面執行過程可以推斷出:

使用NOT EXISTS方式的執行效能嚴重依賴於NOT EXISTS子查詢的執行次數即外層查詢結果集的資料量。

1、當外層查詢結果集的資料量N較小時執行效能較好,如有N=10執行時間為50μs*10=500us=0.005s,再加上一些額外消耗,執行結果也能在0.01秒或10毫秒內範圍,這個響應時間應該能被大部分應用程式接受。

2、當外層程勳結果集的資料量N較大甚至上千萬資料量時,NOT EXISTS的查詢效能會變得非常糟糕,甚至會大量消耗伺服器IOCPU資源從而影響其他業務正常執行。

除上述問題外,在優化過程中發現本應該儲存相同資料的resource_id列在兩個表中定義不同,一表為VARCHAR而另外一表為BIGINT,外部結果集的欄位型別和NOT EXIST字表中欄位型別不同導致NOT EXISTS子查詢中無法使用索引,使得子查詢效能較差,最終影響整個查詢的執行效能

相關推薦

SQL優化案例--使用LEFT JOIN替換NOT EXISTS查詢

轉載  在一些業務場景中,會使用NOT EXISTS語句確保返回資料不存在於特定集合,部分同事會發現NOT EXISTS有些場景效能較差,甚至有些網上謠言說”NOT EXISTS不走索引”,哪對於NOT EXISTS語句,我們如何優化呢?##=================

關於T-SQLexists或者not exists查詢的“偽優化”的做法

png tro ges width 9.png 當前 color 盡心 alt 問題起源 在使用t-sql中的exists(或者not exists)子查詢的時候,不知道什麽時候開始,發現一小部分人存在一種“偽優化”的一些做法,並且向不明真相

MySQL SQL 優化案例JOIN派生表

優化之前: SELECT ap.institution_id, date(ra.create_time) date, sum( IF ( ra.confirm_amount > ld.debit_amount, ld.d

MySQL Execution Plan--NOT EXISTS查詢優化

次數 .com HERE 毫秒 存在 數據 統計 圖片 兩個 在很多業務場景中,會使用NOT EXISTS語句來確保返回數據不存在於特定集合,部分場景下NOT EXISTS語句性能較差,網上甚至存在謠言"NOT EXISTS無法走索引"。 首先需要明確的是:索引不是萬能的

sql語句優化:用join取代not in

寫了好幾個頁面,速度都上不去,瓶頸在於SQL查詢。太多的表,太多的not in,總是從一大推表和資料中篩選出一點資料。看了很多關於SQL優化的文章,都強烈要求不要太多使用not in查詢,最好用表連線來取代它。如:select ID,name from Table_A wh

sql語句中left join、right join、inner join的區別

select http img image ner -s style nbsp color left join(左聯接) 返回包括左表中的所有記錄和右表中聯結字段相等的記錄; right join(右聯接) 返回包括右表中的所有記錄和左表中聯結字段相等的記錄;inner j

SQL優化案例-使用with as優化Subquery Unnesting(七)

使用 no_unnest hint可以讓執行計劃產生filter,即不展開,但一般情況下使用unnest hint無法消除filter。 如下SQL,找出庫中非唯一索引,那麼大家可能會這麼寫SQL: SELECT SEGMENT_NAME,SUM(BYTES/1024/1024) m FRO

SQL優化案例-分割槽索引之無字首索引(六)

無字首索引:分割槽索引不包含分割槽欄位就叫無字首索引,那麼什麼時候用無字首索引和字首索引呢? SQL文字如下,跨分割槽查詢,分割槽欄位post_date(為保證客戶隱私,已經將註釋和文字部分去掉): 跨30個分割槽執行了6分鐘。 SELECT /*+index(I IND_DATE_CO

SQL優化案例-單表分頁語句的優化(八)

分頁語句分為單表分頁與多表關聯分頁。分頁語句的優化首先要選對分頁框架,錯誤的分頁框架會導致掃描表中全部的資料,正確的分頁框架會利用到rownum的count stopkey特性較少資料訪問。 如下錯誤的分頁框架: SELECT * FROM (SELECT T.*, ROWNUM RN

SQL語句:left join後面加上where條件

select a.*,b.* from table1 a left join table2 b on b.X=a.X where XXX 如上SQL:一旦使用了left join,沒有where條件時,左表table1會顯示全部內容     而使用了where,只有滿足where條

Sql語句用left join 解決多表關聯問題(關聯套關聯,例子和原始碼)

帖子是原創是,但是在csdn中高手幫我給解決了,其實就是別名,給自己上了一堂別名的課,所謂別人是高手,其實就是自己是菜鳥吧! 表1:------------------------------ 【人事表】     表名:【Man】     欄位: Man_Id,Man_N

關於Linq to Sql 中的left join 中defaultifempty的相關注意事項

            var q = (from c in                          (from a1 in db.StoreIns                           group a1 by a1.StoreNum into g                 

SQL 中的 left join 外連線

left join 是 left outer join 的簡寫,left join 預設是 outer 屬性的。 account 表 custom 表 0 基礎 inner join left join 外連線包括

SQL優化案例分享(一)union和union all

#優化前:110s,優化後:0.185s 要善於檢視執行計劃:unique的cost是最大的,佔到了很多。 情形一:子查詢中多用union。 我們都知道,最小範圍unique可以提高速度,因此在sql子查詢中,儘可能避免寫union all,如果邏輯上改變不了,那麼就改

SQL語句中left join、right join 以及inner join的區別

在SQL語句中使用的連線通常有以下三種連線: left join(左聯接) 返回包括左表中的所有記錄和右表中聯結欄位相等的記錄 right join(右聯接) 返回包括右表中的所有記錄和左表中聯結欄位相等的記錄 inner join(等值連線) 只返回兩個

sql深入】left join、right join & inner join的比較

    做了很久的前端,如今轉戰到後臺有很多東西還是需要自己去學習的,在專案中學習到了聯合查詢的另一種實現方式,左連線,右連結,等值連線,方便了我們在多表查詢,避免了巢狀寫多個查詢語句的“窘境”!  

SQL優化案例精彩連載(一)

導讀 知數堂致力於為學員的職場之路保駕護航,課上課下不遺餘力為廣大學員排憂解難! SQL優化課鄭鬆華老師根據幫學員優化的案例為原型,和大家分享各式優化思路,本文為連載系列第一篇,將不定期陸續更新,敬請關注! 待優化場景 執行計劃見下:

SQL優化理論基礎:MySQL架構總覽、查詢執行流程、SQL解析順序(轉載)

前言:   一直是想知道一條SQL語句是怎麼被執行的,它執行的順序是怎樣的,然後檢視總結各方資料,就有了下面這一篇博文了。   本文將從MySQL總體架構--->

Left join 中right方條件查詢問題

Left join 查詢時候 需要對right表進行查詢時  在Where後加right的條件 會使查詢結果表位inner join 的結構 這時要把right的條件加在 on 後邊 達到預期效果 這個預期效果   SELECT    

不使用left-join等多表關聯查詢,只用單表查詢和Java程式,簡便實現“多表查詢”效果

上次我們提到,不使用left-loin關聯查詢,可能是為了提高效率或者配置快取,也可以簡化一下sql語句的編寫。只寫單表查詢,sql真得太簡單了。問題是,查詢多個表的資料還是非常需要的。   因此,存在這麼一個強烈的需求:查詢2個集合,怎麼合併2個集合中的資料為1個集合,且資料關聯要正確。