【高性能MySQL】查詢性能優化

合理的表結構、索引對于高性能查詢來說是必不可少的。但是還需要合理的設計查詢。如果查詢寫得很糟糕,那么表結構再合理、索引再合適,也無法實現高性能。
因此高性能的查詢依賴于這三點:查詢優化、索引優化、表結構優化。

為什么查詢速度會慢

如果把查詢看作是一個任務,那么它由一系列子任務組成,每個子任務都會消耗一定的時間。如果要優化查詢,實際上要優化其子任務,要么消除其中一些子任務,要么減少子任務的執行次數,要么讓子任務運行得更快。
查詢的生命周期:從客戶端,到服務器,然后在服務器上進行解析,生成執行計劃,執行(包括調用存儲引擎及調用后的排序、分組等數據處理),并返回結果給客戶端。
在完成這些任務時,查詢需要在不同地方花費時間,包括網絡,CPU 計算,生成統計信息和執行計劃、鎖等待等操作。

優化數據訪問

查詢性能低下的原因可能是以下兩種:

  1. 應用程序可能檢索了超過需要的數據(訪問了太多的行或者太多的列)。
  2. MySQL 服務器層可能在分析大量超過需要的數據行。
請求了不需要的數據
  1. 應用程序中做分頁查詢。
  2. 只查找確實需要的列,不用 SELECT *。
  3. 不要做重復查詢。
MySQL 在掃描額外的記錄

在確定了查詢只返回需要的數據以后,接下來應該看查詢為了返回結果是否掃描了過多的數據。最簡單的衡量查詢開銷的三個指標如下:

  • 響應時間
  • 掃描的行數
  • 返回的行數

一般 MySQL 使用如下三種方式應用 WHERE 條件,從好到壞依次為:

  • 在索引中使用 WHERE 條件來過濾不匹配的記錄。這是在存儲引擎層完成的。
  • 使用覆蓋索引返回記錄,直接從索引中過濾不需要的記錄并返回命中的結果。這是在 MySQL 服務器層完成的,但無需再回表查詢記錄。
  • 從數據表中返回數據,然后過濾不滿足條件的記錄。這是在 MySQL 服務器層完成的,MySQL 需要先從數據表讀出記錄然后過濾。

如果發現查詢需要掃描大量的數據但只返回少數的行,可以這么做:

  • 使用覆蓋索引掃描
  • 改變庫表結構。例如使用單獨的匯總表。
  • 重寫復雜的查詢。

重構查詢的方式

一個復雜查詢還是多個簡單查詢

一般情況下,能用一個查詢解決的事就不要用多個查詢。因為每次查詢都有網絡通信、查詢解析和優化的過程。但是也有例外。因為 MySQL 從設計上讓連接和斷開連接都很輕量級,在返回一個小的查詢結果方面很高效。

切分查詢

比如需要將某張表的全部數據做DML操作,可以分多次進行。防止一次鎖住很多數據、占滿整個事務日志、耗盡系統資源、阻塞很多小的但重要的查詢。

分解關聯查詢

將一個關聯查詢分解為多個查詢的優勢:

  • 讓緩存效率更高
  • 減少鎖的競爭
  • 便于對數據庫進行拆分
  • 查詢本身效率可能會有所提高,如用 in()代替關聯查詢,可以讓MySQL 按照 ID 順序查詢,這可能比隨機的關聯要更高效。
  • 可以減少冗余記錄的查詢。應用層做關聯查詢,意味著對于某條記錄應用只需要查詢一次,而在數據庫中做關聯查詢,則可能需要重復地訪問一部分數據。

查詢執行的基礎

MySQL 執行一個查詢的過程,到底做了些什么:

Screen Shot 2017-05-15 at 10.45.27.png
  1. 客戶端發送一條查詢給服務器。
  2. 服務器檢查查詢是否可以命中緩存,命中則直接返回。否則進入下一階段。
  3. 服務器進行 SQL 解析、預處理,再由優化器生成對應的執行計劃。
  4. 調用存儲引擎的 API 來執行查詢
  5. 返回結果給客戶端
客戶端/服務器通信協議

通過抓包軟件分析,可以看到 MySQL 客戶端和服務器之間是通過 TCP 和 mysql 協議進行通信的。具體細節這里就不講了,我也沒仔細看。目前我們只要大致理解通信協議是如何工作的就夠了。

  • 通信協議是“半雙工”的:任意一個時刻,要么是服務器向客戶端發送數據,要么是客戶端向服務器發送數據。無法進行流量控制,一旦一端開始發送消息,另一端要接受完整消息才能響應它。
  • max_allowed_packet 參數可以限制數據包的長度。
  • 服務器響應給用戶的數據通常很多,由多個數據包組成。
  • 客戶端接受數據一般是將全部結果集緩存到內存中。這樣可以減少服務器的壓力。
查詢緩存

在解析查詢語句之前,如果查詢緩存是打開的,那么 MySQL 會優先檢查這個查詢是否命中查詢緩存中的數據。沒命中則走下一個階段。命中了,在返回結果之前還會檢查用戶權限。如果權限沒問題,則直接返回數據給客戶端。這種情況下,查詢不會被解析,不用生成執行計劃,不會被執行。

查詢優化處理

查詢的生命周期下一步是將 SQL 轉化成執行計劃。然后再按照執行計劃和存儲引擎交互。這包括多個子階段:解析 SQL,預處理,優化執行計劃。一條查詢可能有多種執行方式,最后都返回相同的結果。優化器的作用就是找到其中最好的執行計劃。

查詢執行引擎

存儲引擎根據查詢計劃來完成查詢。

返回結果給客戶端

查詢執行的最后一個階段是返回結果給客戶端。即使客戶端不需要結果,也會返回這個查詢的一些信息,如該查詢影響到的行數。MySQL 將結果集返回給客戶端是一個增量、逐步返回的過程。好處是服務器不需要緩存太多的結果,客戶端也能第一時間獲得返回的結果。

優化特定類型的查詢

  • COUNT()
  • 關聯查詢
  • 子查詢
  • GROUP BY 和 DISTINCT
  • LIMIT 分頁
  • UNION
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,983評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,772評論 3 422
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,947評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,201評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,960評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,350評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,406評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,549評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,104評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,914評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,089評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,647評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,340評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,753評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,007評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,834評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,106評論 2 375

推薦閱讀更多精彩內容