MySQL Using temporary; Using filesort INNER JOIN優化

来源:http://www.cnblogs.com/zhulin516114/archive/2017/08/29/7448037.html
-Advertisement-
Play Games

問題 通過「SHOW FULL PROCESSLIST」語句很容易就能查到問題SQL,如下: 說明:因為post和tag是多對多的關係,所以存在一個關聯表post_tag。 試著用EXPLAIN查詢一下SQL執行計劃(篇幅所限,結果有刪減): 下麵給出優化後的SQL,唯一的變化就是把連接方式改成了「 ...


問題

通過「SHOW FULL PROCESSLIST」語句很容易就能查到問題SQL,如下:

SELECT post.*
FROM post
INNER JOIN post_tag ON post.id = post_tag.post_id
WHERE post.status = 1 AND post_tag.tag_id = 123
ORDER BY post.created DESC
LIMIT 100

說明:因為post和tag是多對多的關係,所以存在一個關聯表post_tag。

試著用EXPLAIN查詢一下SQL執行計劃(篇幅所限,結果有刪減):

+----------+---------+-------+-----------------------------+
| table    | key     | rows  | Extra                       |
+----------+---------+-------+-----------------------------+
| post_tag | tag_id  | 71220 | Using where; Using filesort |
| post     | PRIMARY |     1 | Using where                 |
+----------+---------+-------+-----------------------------+

下麵給出優化後的SQL,唯一的變化就是把連接方式改成了「STRAIGHT_JOIN」:

SELECT post.*
FROM post
STRAIGHT_JOIN post_tag ON post.id = post_tag.post_id
WHERE post.status = 1 AND post_tag.tag_id = 123
ORDER BY post.created DESC
LIMIT 100

試著用EXPLAIN查詢一下SQL執行計劃(篇幅所限,結果有刪減):

+----------+----------------+--------+-------------+
| table    | key            | rows   | Extra       |
+----------+----------------+--------+-------------+
| post     | status_created | 119340 | Using where |
| post_tag | post_id        |      1 | Using where |
+----------+----------------+--------+-------------+

對比優化前後兩次EXPLAIN的結果來看,優化後的SQL雖然「rows」更大了,但是沒有了「Using filesort」,綜合來看,性能依然得到了提升。

提醒:註意兩次EXPLAIN結果中各個表出現的先後順序,稍後會解釋。

解釋

對第一條SQL而言,為什麼MySQL優化器選擇了一個耗時的執行方案?對第二條SQL而言,為什麼把連接方式改成STRAIGHT_JOIN之後就提升了性能?

這一切還得從MySQL對多表連接的處理方式說起,首先MySQL優化器要確定以誰為驅動表,也就是說以哪個表為基準,在處理此類問題時,MySQL優化器採用了簡單粗暴的解決方法:哪個表的結果集小,就以哪個表為驅動表,當然MySQL優化器實際的處理方式會複雜許多,具體可以參考:MySQL優化器如何選擇索引和JOIN順序

說明:在EXPLAIN結果中,第一行出現的表就是驅動表。

繼續post連接post_tag的例子,MySQL優化器有如下兩個選擇,分別是:

  • 以post為驅動表,通過status_created索引過濾,結果集119340行
  • 以post_tag為驅動表,通過tag_id索引過濾,結果集71220行

顯而易見,post_tag過濾的結果集更小,所以MySQL優化器選擇它作為驅動表,可悲催的是我們還需要以post表中的created欄位來排序,也就是說排序欄位不在驅動表裡,於是乎不可避免的出現了「Using filesort」,甚至「Using temporary」。

知道了來龍去脈,優化起來就容易了,要儘可能的保證排序欄位在驅動表中,所以必須以post為驅動表,於是乎必須藉助「STRAIGHT_JOIN」強制連接順序。

實際上在某些特殊情況里,排序欄位可以不在驅動表裡,比如驅動表結果集只有一行記錄,並且在連接其它表時,索引除了連接欄位,還包含了排序欄位,此時連接表後,索引中的數據本身自然就是排好序的。

既然聊到這裡順帶說點題外話,大家可能會遇到類似下麵的問題:原本運行良好的查詢語句,過了一段時間後,可能會突然變得很糟糕。一個很大可能的原因就是數據分佈情況發生了變化,從而導致MySQL優化器對驅動表的選擇發生了變化,進而出現索引失效的情況,所以沒事最好多查查,關註一下這些情況。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1. 簡述 在實際開發中,常常需要進行不同應用程式之間的數據通信,例如讀取聯繫人列表等等,ContentProvider就是Android提供的用於實現不同進程之間進行數據通信的類。 ContentProvider的作用是對外提供對本應用的數據進行“增刪改查”的介面,而後在其它程式可通過Conten ...
  • 有時候在優化UI界面時,會惹怒用戶。那麼,如何有效的去避免呢,我們來一起看看有哪些優化UI界面的方法。 ...
  • 從github下載資料過程中,有些項目含有子模塊,有時通過git clone 或者下載zip方式項目可能會缺少文件,因此需要執行git submodule update --init --recursive 命令來將子模塊也下載到項目中 ...
  • 1.創建存儲過程 CREATE PROCEDURE updateGatwxLiveStatus() BEGIN UPDATE gatwxlive SET STATUS = '3'WHERE 1=1and `status`='1'and liveurl='404'; END;2.查看job是否已開 s ...
  • 原文地址: https://zhuanlan.zhihu.com/p/23309693 https://zhuanlan.zhihu.com/p/23293860 CTC:前向計算例子 這裡我們直接使用warp-ctc中的變數進行分析。我們定義T為RNN輸出的結果的維數,這個問題的最終輸出維度為al ...
  • 之前項目中需要寫一個sql,就是查出某個調研詳情中,選A答案,B答案,C答案...F答案的人各有多少人,這個sql也是費了很大的力氣才寫出來,故記下來,方便以後使用。 其中tbl_research_item為調研詳情表,tbl_user_research_item為用戶答題詳情表 由於每道調研的題目 ...
  • Myeclipse 新建數據源 一、打開myeclipse(打開了當我沒說) 二、在window選項中找到show view ,點擊other,輸入db,選擇DB Browser 三、在DB Browser 視窗 右鍵點擊 選擇new 四、出現下麵界面,填寫所需的信息 jia包下載地址:https: ...
  • 在最近的項目中,有用到動態執行sql語句,SQL為我們提供了兩種動態執行SQL語句的命令,分別是EXEC和sp_executesql;通常,sp_executesql則更具有優勢,它提供了輸入輸出介面,而EXEC沒有。還有一個最大的好處就是利用sp_executesql,能夠重用執行計劃,這就大大提 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...