MySQL in UnionAll結果集的優化
問題還是前面的問題
http://blog.itpub.net/29254281/viewspace-1878089/
http://blog.itpub.net/29254281/viewspace-1961333/
MySQL 5.6.14
需求:
找使用者和使用者朋友唱的歌,按照時間排序,返回最近的30個.
原來的SQL:
執行時間:0.28s
執行計劃:
![](https://i.iter01.com/images/4339b547ce2d3bb9edce7d7fb24e82b15270abe18ed69c525d8dd347784dd01b.png)
現象:
如果使用者加的好友非常多,比如一口氣加了幾萬好友,則這個SQL非常快.
如果使用者只是加了十幾個好友,則這個SQL很慢.
上面的使用者只是加了幾個好友,所以執行的很慢.
為什麼走了索引全掃描呢?
space_av是使用者的歌曲作品表,資料量非常的大.
如果in子查詢中沒有union all則執行計劃如下:
如果in子查詢返回的結果比較少,執行計劃如下:
![](https://i.iter01.com/images/dbc41ecfc1afc6a9eb927dc6a105572c7db381010a9562903a7038f14e5c405f.png)
因為結果集比較小,所以即使有排序,問題也不大.
如果in子查詢返回的結果很多,則執行計劃如下:
![](https://i.iter01.com/images/2c325b0dae1d51480675a40900f2c6963ec7a6472c6d67b974dee3dfc5c78401.png)
走索引全掃描,但是使用索引消除排序,所以速度也很快.
問題來了,一開始的那個SQL in (select xx union all select xx)
in 子查詢返回的結果集很小,但是優化器選擇了走索引全掃描.
可能是因為MySQL 認為子查詢中有union all 結果集一定很大,所以走了索引全掃描。
但是,如果子查詢中union all返回的結果很小,則效能直線下降.
一種變通的優化方法:騙優化器說,這不是一個包含union all的子查詢.
那麼在子查詢返回結果集小的時候,執行計劃如下:
![](https://i.iter01.com/images/0b3bb665e726972035a19d56310adec23f31286c263a0bee3c4d263797bcee71.png)
在子查詢返回結果集很大的時候,執行計劃如下:
![](https://i.iter01.com/images/3467923bedeffd61e926b8a548d45873f2bef1daf8154dd61a53cd5b34c1a55c.png)
恩,根據返回結果,都走了正確的執行計劃.
僅僅是因為在 union all 外面又套了一層,讓優化器感知不到子查詢中包含了union all
http://blog.itpub.net/29254281/viewspace-1878089/
http://blog.itpub.net/29254281/viewspace-1961333/
MySQL 5.6.14
需求:
找使用者和使用者朋友唱的歌,按照時間排序,返回最近的30個.
原來的SQL:
- select
- 1 dynamicType,
- - 1 shareID,
- AVID,
- createTime,
- userID,
- commentTimes,
- fromIP,
- praiseTimes
- from
- space_av
- where
- userid in (select
- toUserID
- from
- space_friend
- where
- userID = 901164037 union all select 901164037)
- order by createTime DESC
- limit 30;
執行時間:0.28s
執行計劃:
![](https://i.iter01.com/images/4339b547ce2d3bb9edce7d7fb24e82b15270abe18ed69c525d8dd347784dd01b.png)
現象:
如果使用者加的好友非常多,比如一口氣加了幾萬好友,則這個SQL非常快.
如果使用者只是加了十幾個好友,則這個SQL很慢.
上面的使用者只是加了幾個好友,所以執行的很慢.
為什麼走了索引全掃描呢?
space_av是使用者的歌曲作品表,資料量非常的大.
如果in子查詢中沒有union all則執行計劃如下:
- explain
- select
- 1 dynamicType,
- - 1 shareID,
- AVID,
- createTime,
- userID,
- commentTimes,
- fromIP,
- praiseTimes
- from
- space_av
- where
- userid in (select
- toUserID
- from
- space_friend
- where
- userID = 901164037)
- order by createTime DESC
- limit 30;
如果in子查詢返回的結果比較少,執行計劃如下:
![](https://i.iter01.com/images/dbc41ecfc1afc6a9eb927dc6a105572c7db381010a9562903a7038f14e5c405f.png)
因為結果集比較小,所以即使有排序,問題也不大.
如果in子查詢返回的結果很多,則執行計劃如下:
![](https://i.iter01.com/images/2c325b0dae1d51480675a40900f2c6963ec7a6472c6d67b974dee3dfc5c78401.png)
走索引全掃描,但是使用索引消除排序,所以速度也很快.
問題來了,一開始的那個SQL in (select xx union all select xx)
in 子查詢返回的結果集很小,但是優化器選擇了走索引全掃描.
可能是因為MySQL 認為子查詢中有union all 結果集一定很大,所以走了索引全掃描。
但是,如果子查詢中union all返回的結果很小,則效能直線下降.
一種變通的優化方法:騙優化器說,這不是一個包含union all的子查詢.
- SELECT
- 1 AS dynamicType,
- - 1 AS shareID,
- AVID,
- createTime,
- userID,
- commentTimes,
- fromIP,
- praiseTimes
- FROM
- space_av
- WHERE
- userid IN
- (
- SELECT
- toUserID
- FROM
- (
- SELECT
- toUserID
- FROM
- space_friend
- WHERE
- userID = 901164037
- UNION ALL
- SELECT 901164037
- ) tmp
- )
- ORDER BY createTime DESC
- LIMIT 30
那麼在子查詢返回結果集小的時候,執行計劃如下:
![](https://i.iter01.com/images/0b3bb665e726972035a19d56310adec23f31286c263a0bee3c4d263797bcee71.png)
在子查詢返回結果集很大的時候,執行計劃如下:
![](https://i.iter01.com/images/3467923bedeffd61e926b8a548d45873f2bef1daf8154dd61a53cd5b34c1a55c.png)
恩,根據返回結果,都走了正確的執行計劃.
僅僅是因為在 union all 外面又套了一層,讓優化器感知不到子查詢中包含了union all
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29254281/viewspace-1968995/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- HttpRunner 的結果校驗器優化HTTP優化
- MySQL的SQL效能優化總結MySql優化
- MySQL EXPLAIN結果集分析 - 附帶大量案例MySqlAI
- Tableau視覺化結果的優化小技巧(二)視覺化優化
- 簡單的mysql儲存過程,輸出結果集MySql儲存過程
- Sql_從查詢的結果集中分組後取最後有效的資料成新的結果集小記(待優化)SQL優化
- mysql返回一個結果集的儲存過程小例子MySql儲存過程
- iOS FMDB有返回結果集和無返回結果集iOS
- mysql查詢效能優化總結MySql優化
- MySQL 8 大叢集架構的優缺點總結MySql架構
- 《MySQL 效能優化》之理解 MySQL 體系結構MySql優化
- Mysql效能最佳化(三)--explain返回的結果說明MySqlAI
- mysql group by 取想要的結果MySql
- MySQL 索引及查詢優化總結MySql索引優化
- 結果集 (ResultSet)全面解析
- 批次對比結果集
- MySQL優化(1)——–常用的優化步驟MySql優化
- mysql優化MySql優化
- Mysql 優化MySql優化
- 3萬字總結,Mysql優化之精髓MySql優化
- MySQL效能結構優化原理(技術核心)MySql優化
- h5效能優化,細節決定結果。H5優化
- 史上更全的 MySQL 高效能優化實戰總結!MySql優化
- 史上更全的MySQL高效能優化實戰總結!MySql優化
- MySQL架構的優化MySql架構優化
- mysql常用的優化操作MySql優化
- MySQL 的查詢優化MySql優化
- 關於mysql的優化MySql優化
- (mysql優化-3) 系統優化MySql優化
- mysql鎖機制總結,以及優化建議MySql優化
- MySQL(二) MySql常用優化MySql優化
- mysql優化(一)MySql優化
- mysql order by 優化MySql優化
- mysql效能優化MySql優化
- MySQL表優化MySql優化
- MySQL——效能優化MySql優化
- 舊,優化mysql優化MySql
- MySQL索引優化MySql索引優化
- mysql優化索引MySql優化索引