sql嵌套查詢很慢——優化方案

工做須要寫一個查詢:sql

最開始寫了最原始的嵌套查詢:編程

select * from realservice where realservname in (select realservname from groupmember where groupname in (select groupname from v_group where vname in (select vname from vservice where vip = '10.181.65.185')));

發現很慢,查了一下用時4min 22.74sec。編程語言

而後考慮如何優化,天然想到了鏈接,而後優化後代碼以下:優化

select * from realservice as a join groupmember as b where a.realservname=b.realservname and b.groupname in (select a.groupname from v_group as a join vservice as b where a.vname=b.vname and b.vip = '10.181.65.185');

用時0.03sec,已經很快了,可是出於好奇,想知道把in和=的區別,繼續改進:.net

select * from realservice as a join groupmember as b where a.realservname=b.realservname and b.groupname=(select a.groupname from v_group as a join vservice as b where a.vname=b.vname and b.vip = '10.181.65.185');

用時0.00sec!!!!指針

 

因此先來了解下in和=的區別:code

等號:確切知道所要查找的內容,且爲單一值時,可使用等號運算符來進行數據比較。等號運算符中可使用字符串、日期或數字。blog

in:當確切知道所要查找的內容,且爲多個值時,可使用 IN 子句來進行數據比較。IN 子句中也可使用數字、字符串或日期。ip

這裏子查詢出來的groupname只有一個,是單一值,因此可使用等號,但若是groupname查詢出來的結果是多個,再使用等號就會出錯,此時只能使用in來查詢了。內存

因爲groupname有可能會出現有多個值的狀況,因此爲了保證查詢的正確,這裏應該使用in而不是等號。

 

而後看一下爲何直接使用多層嵌套查詢會很慢?咱們先看一下select查詢的本質:

分析器會先看語句的第一個詞,當它發現第一個詞是SELECT關鍵字的時候,它會跳到FROM關鍵字,而後經過FROM關鍵字找到表名並把表裝入內存。接着是找WHERE關鍵字,若是找不到則返回到SELECT找字段解析,若是找到WHERE,則分析其中的條件,完成後再回到SELECT分析字段。最後造成一張咱們要的虛表。
WHERE關鍵字後面的是條件表達式。若是學過C語言等編程語言就會知道,條件表達式計算完成後,會有一個返回值,即非0或0,非0即爲真(true),0即爲假(false)。同理WHERE後面的條件也有一個返回值,真或假,來肯定接下來執不執行SELECT。

分析器先找到關鍵字SELECT,而後跳到FROM關鍵字將STUDENT表導入內存,並經過指針p1找到第一條記錄,接着找到WHERE關鍵字計算它的條件表達式,若是爲真那麼把這條記錄裝到一個虛表當中,p1再指向下一條記錄。若是爲假那麼p1直接指向下一條記錄,而不進行其它操做。一直檢索完整個表,並把虛表返回給用戶。

這是一個SQL語句的嵌套使用,但和上面說的SQL語句的執行過程也是相同的。嵌套的意思也就是說當分析主SQL語句(外面的那個SELECT)到WHERE關鍵字的時候,又進入了另外一個SQL語句中。那麼也就是說,分析器先找到表Student並裝入內存,一個指針(例如p1)指向Student表中的第一條記錄。而後進入WHERE裏分析裏面的SQL語句,再把SC表裝入內存,另外一個指針(例如p2)指向SC表中的第一條記錄,分析WHERE後面的條件表達式,依次進行分析,最後分析出一個虛表2。

 若是虛表爲空表,EXISTS 虛表2 也就爲false,不返回到SELECT,而p1指向下一條記錄。若是虛表2不爲空也就是有記錄,那麼EXISTS 虛表2 爲true同,返回到SELECT並把p1指向的記錄添加到主SQL語句的虛表1當中。(這也是爲何嵌套的SQL語句SELECT 後面爲通常爲*的緣由,由於它EXISTS返回的只是真或假,字段的名沒有意義,用*就行,固然用別的也不會錯。 )

注意,這裏雖然嵌套的SQL語句分析完了,但主SQL語句只執行了一遍,也就是說p1指向Student的第一條記錄,p1還要再指向Student表的下一條記錄並分析,這樣又進入了嵌套中的SQL語句,同上面說的同樣分析。當p1也到了Student表的結尾,整個SQL語句結束。返回虛表1Sname這一列。

因此,才說嵌套查詢的複雜度是M*N次查詢,由於每一條數據都要和一次子查詢的查詢結果進行比對,同時,每次查詢分析到from的時候都會把表裝進一次內存,建立一次臨時表,M*N次的存入內存也是很大的消耗。

參考連接:

https://blog.csdn.net/jiankunking/article/details/23590239

https://blog.csdn.net/MTbaby/article/details/79860796

相關文章
相關標籤/搜索