技術分享 | MySQL 查詢優化

文章轉載自公衆號:MySQL解決方案工程師 , 做者 徐軼韜

本文中具體內容,能夠關注公衆號:愛可生開源社區,觀看網絡研討會的視頻數據庫


上週徐軼韜老師在 MySQL 團隊的網絡研討會上,分享了 MySQL 查詢優化相關內容,如下是相關內容整理,供各位參考。服務器

內容分爲以下幾個方面:網絡

1. 基於成本的 MySQL 查詢優化。
2. 監視、分析和查詢優化的工具備哪些?
3. 數據訪問方法與如何選擇索引。
4. 如何對鏈接進行優化。
5. 如何影響優化器。接下來,簡明介紹一下相關內容。函數


1. 基於成本的 MySQL 查詢優化:

MySQL 的優化器將 SQL 查詢做爲輸入,併產生一個計劃來執行該查詢。
例如,應該按什麼順序鏈接表以及應該使用哪些索引。目標是可以從衆多可能的執行計劃中找到最佳的執行計劃。工具

MySQL 使用基於成本的優化器。計劃的成本大體反映了查詢所需的資源,其中主要因素是計算查詢時將要訪問的行數。在優化過程當中,優化器會選擇鏈接順序,決定使用哪一個索引等等。同時,優化器還會根據從存儲引擎獲取的數據的統計信息做出決定。而且還依賴於數據字典中的元數據信息。性能

所以,查詢優化的整體思路如上圖所示。優化

基於成本的查詢優化器將爲不一樣的操做分配成本,如表掃描和索引查找。spa

成本單位是從磁盤讀取隨機數據頁的成本。全部其餘成本數字都與此成本單位有關。基於這些成本,優化器將計算可供選擇的計劃的成本。最終它將選擇成本最低的計劃。插件

這是 MySQL 中成本模型的一個很是簡單的視圖。線程

做爲輸入,它須要基本操做,例如從表格讀取數據或鏈接兩個表格。做爲輸出,它產生對執行此操做的成本的估計。除了成本估算以外,它還會估算該操做產生的行數。成本模型由計算不一樣操做的成本和估計行數的公式組成。除了成本公式以外,成本模型還包含一組「成本常數」。這些是 MySQL 服務器在執行查詢時執行的基本操做的成本。

成本模型使用來自數據字典的信息和來自存儲引擎的統計信息來進行計算。主要的統計信息是表中的行數,對於索引,也得到基數,即有多少個不一樣的列值,以及索引範圍中的行數。從數據字典中,咱們使用關於行和索引的信息:如行和鍵的長度,惟一性以及列是否能夠爲空。
在 MySQL 5.7 中,已經配置了成本模型。成本常數存儲在數據庫表中,能夠更改以更好地表示系統的特徵。

使用這個模型,優化器在大多數狀況下會選擇一個最好的計劃。可是,有時候優化器不能成功找到最佳計劃。這多是因爲其決策所依據的數據不許確或因爲成本模型自己的不許確性。

2. 監視、分析和查詢優化的工具備哪些?

監視分析工具

瞭解 MySQL 的優化器原理以後,咱們來經過一些工具來對 MySQL 的性能進行監視分析。工具包括以下:

MySQL 企業版監控器的查詢分析器提供了一個概覽,使用戶可以快速識別開銷大的查詢。用戶還能夠對單個查詢進行深刻研究,以查看關於查詢的細粒度統計信息。

Performance Schema 有大量的表與性能相關的數據。events_statements_history 表提供最近執行的查詢的統計信息。events_statements_summary_by_digest 表中彙總相似查詢的數據。file_summary_by_event_name 表包含獲取文件 I/O 的統計信息。table_io_waits_summary 表提供有關表和索引使用狀況的統計信息。

語句事件表提供有關最近運行的查詢的信息。
events_statements_current 表將顯示每一個鏈接或線程的當前語句。
歷史表默認給出每一個線程最近的 10 條語句,
history_long 表給出了所有 10000 條最新的語句。
歷史記錄表的大小是可配置的。
已經用紅色標出了這些表格中的最有用的信息。
例如,TIMER_WAIT 給出了執行查詢須要多長時間。單位是皮秒。
ROWS_SENT 是結果中的行數,而 ROWS_EXAMINED 是執行查詢時必須訪問的行數。
ROWS_EXAMINED 比 ROWS_SENT 大得多,一般代表查詢須要優化。
CREATED_TMP_DISK_TABLES 告訴查詢是否建立了磁盤上的臨時表。

語句摘要是將相似查詢分組在一塊兒的一種方法。在這裏你能夠看到兩個查詢的例子,這兩個查詢的區別,僅在於使用的常量。這樣的查詢將獲得相同的摘要。摘要計算也會忽略空白和數值。events_statements_summary_by_digest 表包含每一個摘要彙總的統計信息。DIGEST_TEXT 提供規範化的查詢文本,COUNT_STAR 是執行此類型查詢的次數。SUM_TIMER_WAIT 是執行此查詢所用的總時間,AVG_TIMER_WAIT 是每次執行的平均時間。大多數其餘列是各個查詢的值的總和。在調查最近的性能退化時,FIRST_SEEN 列對於查找可能致使問題的新查詢很是有用。

Performance schema 很是龐大,有不少細節。所以,MySQL 團隊開發了 sys_schema,這是一個視圖,存儲過程和函數的集合,旨在使訪問 Performanceschema 數據變得更加容易。

EXPLAIN 有三種格式,表格,JSON 及可視化。經過使用 EXPLAIN 能夠獲取查詢的執行計劃。
結構化的 EXPLAIN以JSON 格式提供查詢計劃,能夠經過在 EXPLAIN 以後指定 FORMAT= JSON 來得到此信息。使用 JSON 能夠更容易地顯示查詢的結構。MySQL Workbench 使用結構化 EXPLAIN 的輸出來優化查詢計劃。上圖按從左到右的鏈接順序顯示錶。紅色框表示全表掃描,而綠色框表示使用索引查找。對於每一個表,顯示使用的索引。還要注意的是,每一個表格的框上方是每一個表訪問所發現的行數的估計值以及訪問該表的成本。

若是您想更深刻地瞭解爲何選擇某個查詢計劃,那麼優化器跟蹤很是有用。雖然 EXPLAIN 顯示選定的計劃,但優化程序跟蹤顯示爲何選擇計劃:您將可以看到替代計劃,估計成本以及作出的決策。跟蹤採用 JSON 格式。要打開 optimizer_trace,能夠在 optimizer_trace 會話變量中設置 enabled 標誌。解釋或運行查詢後,能夠從 informationschema 中的 optimizer_trace 表中獲取跟蹤。一般會將跟蹤轉存到文件以供進一步檢查。optimizer_trace 表有 3 個其餘列,查詢的文本,Missing_bytes_beyond_max_mem_size。若是這不是零,則須要增長用於捕獲跟蹤的內存緩衝區的大小。insufficient_privileges。若是不爲零,則表示用戶缺少查看有關查詢或查詢中使用的存儲例程的信息的權限。

3. 數據訪問方法與如何選擇索引

數據訪問方法

選擇訪問方法的目標是爲查詢中的每一個表找到讀取所需數據的最佳方式。對於查詢的每一個表,咱們執行如下操做:
檢查訪問方法是否有用,估計使用該訪問方法的成本,以及選擇成本最低的訪問方法。關於訪問方法的詳細內容請關注公衆號:愛可生開源社區,觀看視頻。

4. 如何對鏈接進行優化

鏈接的優化

鏈接優化器的做用是找到鏈接表的最佳順序。咱們的鏈接優化器使用「貪婪搜索策略」來計算全部可能的鏈接順序。這是以深度優先的方式完成的。爲了縮小範圍,將會刪去比迄今爲止發現的最佳計劃花費更多的部分計劃。爲了使這種刪去更高效,首先會對大小和鍵依賴關係進行排序。這樣增長了儘早找到一個好計劃的機會,以便更多的計劃將被刪去。鏈接優化器默認也會刪去一些不那麼有但願的計劃,而這些計劃不必定比目前的最佳計劃花費更多。在某些狀況下,可能會所以而錯過最佳計劃。探索式刪去能夠經過將 optimizer_prune_level 設置爲 0 來關閉。

1. 我如今將展現一個關於鏈接優化器如何工做的例子。咱們的示例查詢加入了三個表格,語言,國家和城市。優化器一般會從最小的表開始。語言是最小的表2. 它首先添加國家3. 而後城市。此鏈接順序的估計總成本爲 265684. 將其記錄爲迄今最好的計劃5. 而後它回溯並添加城市6. 而後是國家。此鏈接順序的總成本爲 32568,比以前的計劃成本大。如今全部以語言開始的可能計劃都已經嘗試過了,咱們將繼續以國家爲起點的計劃。7. 咱們首先添加語言8. 而後城市。總成本是 6279. 因此這個鏈接順序是迄今爲止最好的。10. 而後咱們嘗試將城市做爲第二張表,而且看到這個部分計劃的成本是 1245。11. 這比迄今爲止發現的最佳計劃還要大。所以,咱們將在此中止而且不向此部分鏈接順序添加更多表。12. 咱們繼續與城市和單獨訪問該表的成本是 862。13. 這也比迄今爲止的最低成本要高,咱們將刪去這個搜索樹的其他部分。經過這種方式,鏈接優化器已經肯定最佳鏈接順序是 Country 優先,而後是 Language,而後是 City。

能夠經過改變鏈接的順序進行優化,翻轉鏈接順序,執行時間從 15 秒減小到不到 1 秒。反向順序更好的緣由是,實際上不多有客戶的賬戶餘額很低。所以,經過從客戶表開始,大多數行將被過濾掉,而且實際上不多有查詢到訂單表。

5. 如何影響優化器

影響優化器

能夠經過上圖的方法對優化器進行影響,以達到預期效果。

MySQL 5.7 引入了優化器提示的新語法。

在 SELECT 以後,新的提示應該放在一個特殊的註釋中

這些提示中的許多提示都對應於 optimizer_switch 會話變量能夠控制的功能。這些提示容許打開或關閉單個查詢的功能,或者僅用於查詢的某些表或索引。

MySQL 8.0,已經添加了提示來控制派生表和視圖是否合併。

還添加了幾個鏈接順序提示。這些新的聯接提示比現有的 STRAIGHT_JOIN 提示更靈活,它要求 FROM 子句中的表按特定順序列出。

MySQL 8.0 還能夠在查詢期間臨時設置會話變量。

從 MySQL 5.7 開始,提供了一個插件,可用於在不更改應用程序的狀況下重寫有問題的查詢。

查詢能夠在到達 MySQL 服務器時重寫。

用戶可使用這個插件添加提示,修改鏈接順序等等。

在這張幻燈片的例子中,插入一條規則來將 FORCEINDEX 提示添加到匹配模式的查詢中。與 performance schema 中使用的相同的查詢摘要用於傳入查詢與重寫規則的高效匹配。

這樣,對於不符合任何重寫規則的查詢,應該幾乎沒有開銷。

以上內容是關於 MySQL 查詢優化的一個簡明總結,詳細內容請觀看網絡研討會的視頻。

感謝您關注 MySQL !

相關文章
相關標籤/搜索