MySQL優化:學會使用show profile和trace分析慢查詢

2021-01-10 王者小哆啦

看本篇之前建議先看上篇:MySQL優化:定位慢查詢的兩種方法以及使用explain分析SQL

在上一節我們學習了定位慢 SQL 及使用 explain 分析慢 SQL,我們也提到了分析慢 SQL 還有 show profile 和 trace 等方法,本節就重點補充學習這兩種方法。

show profile 分析慢查詢

NO.1 使用 profile 分析慢查詢

大致步驟:

確定這個 MySQL 版本是否支持 profile;確定 profile 是否關閉;如果關閉開啟 profile;在伺服器端發送要執行的 SQL;查看執行完 SQL 的 query id;通過 query id 查看 SQL 的每個狀態及耗時時間;停止profile;

獲取profile 使用 help profile即可

mysql> help profile;

1.1 確定是否支持 profile

mysql> select @@have_profiling;

如果結果是YES表示支持。

1.2 查看 profiling 狀態

mysql> select @@profiling;

0表示關閉,1表示開啟,默認是關閉的。

使用如下命令開啟:mysql> set profiling=1;

1.3 執行要分析的sql語句

mysql> select * from test_table where d=90000;

執行完成SQL後再執行:show profiles;得到profile id。

1.4 根據profile id查詢指定SQL執行詳情

通過 show profile for query id 可看到執行過的 SQL 每個狀態和消耗時間:

MySQL [test]> show profile for query 1;

通過以上結果,可以確定 SQL 執行過程具體在哪個過程耗時比較久,從而更好地進行 SQL 優化與調整。

注意:「show profiles」已棄用,SHOW PROFILES將來會被Performance Schema替換掉,但是現在還是非常非常實用的,8.0目前還在支持中。

小計:實用show profile 可以直接查看上一條SQL語句的執行開銷

MySQL [test]> show profile;

NOTE:show profile自身不會產生Profiling。

查看指定SQL的CPU開銷:MySQL [test]> show profile cpu for query 1;

查詢指定SQL的內存開銷:MySQL [test]> show profile memory for query 1;

小技巧:給大家分享一條SQL,查詢某條SQL開銷並且按照耗時倒敘排序

SET @query_id = 1; // 設置要查詢的 profile id,然後執行如下SQL即可SELECT STATE, SUM(DURATION) AS Total_R,ROUND(100 * SUM(DURATION) /(SELECT SUM(DURATION)FROM INFORMATION_SCHEMA.PROFILING WHERE QUERY_ID = @query_id ), 2) AS Pct_R,COUNT(*) AS Calls,SUM(DURATION) / COUNT(*) AS "R/Call" FROM INFORMATION_SCHEMA.PROFILING WHERE QUERY_ID = @query_id GROUP BY STATE ORDER BY Total_R DESC;

注意:Mysql所有的profile都被記錄到了information_schema.profiling表。

1.5 關閉profile

mysql> set profiling=off;

trace 分析 SQL 優化器

從前面學到了 explain 可以查看 SQL 執行計劃,但是無法知道它為什麼做這個決策,如果想確定多種索引方案之間是如何選擇的或者排序時選擇的是哪種排序模式,有什麼好的辦法嗎?

從 MySQL 5.6 開始,可以使用 trace 查看優化器如何選擇執行計劃。

通過trace,能夠進一步了解為什麼優化器選擇A執行計劃而不是選擇B執行計劃,或者知道某個排序使用的排序模式,幫助我們更好地理解優化器行為。

如果需要使用,先開啟 trace,設置格式為 JSON,再執行需要分析的 SQL,最後查看 trace 分析結果(在 information_schema.OPTIMIZER_TRACE 中)。

注意:開啟該功能,會對 MySQL 性能有所影響,因此只建議分析問題時臨時開啟。

這裡利用我們上篇:MySQL優化:定位慢查詢的兩種方法以及使用explain分析SQL中創建的數據表test_table;

在test_table中除了d欄位,abc欄位都有索引。執行如下sql

explain select * from test_table where a=90000 and b=90000 order by a;

通過上面執行計劃中 key 這個欄位可以看出,該語句使用的是 b 欄位的索引 idx_a。實際表 t1 中,a、b 兩個欄位都有索引,為什麼條件中有這兩個索引欄位卻偏偏選了 a 欄位的索引呢?這時就可以使用 trace 進行分析。

大致步驟如下:

開啟trace分析器執行要查詢的sql查看分析結果關閉trace分析器

NO.1 開啟trace分析器

MySQL [test]> set session optimizer_trace="enabled=on";

NO.2 執行要查詢的SQL

MySQL [test]> select * from test_table where a=90000 and b=90000 order by a;

NO.3 查詢分析結果

MySQL [test]> SELECT * FROM information_schema.OPTIMIZER_TRACE\G

注意:在返回的steps數組中可以查看詳細mysql都幹了什麼。

不好意思,因為排版導致內容太長大家可以百度一下參數含義。

NO.4 關閉trace分析器

mysql> set session optimizer_trace="enabled=off";

TRACE 欄位中整個文本大致分為三個過程

準備階段:對應文本中的 join_preparation優化階段:對應文本中的 join_optimization執行階段:對應文本中的 join_execution

使用時,重點關注優化階段和執行階段。

知識點拓展:

知識點一:MySQL 常見排序模式:

< sort_key, rowid >雙路排序(又叫回表排序模式):是首先根據相應的條件取出相應的排序欄位和可以直接定位行數據的行 ID,然後在 sort buffer 中進行排序,排序完後需要再次取回其它需要的欄位;< sort_key, additional_fields >單路排序:是一次性取出滿足條件行的所有欄位,然後在sort buffer中進行排序;< sort_key, packed_additional_fields >打包數據排序模式:將 char 和 varchar 欄位存到 sort buffer 中時,更加緊縮。

三種排序模式比較:

第二種模式相對第一種模式,避免了二次回表,可以理解為用空間換時間。由於 sort buffer 有限,如果需要查詢的數據比較大的話,會增加磁碟排序時間,效率可能比第一種方式更低。MySQL 提供了一個參數:max_length_for_sort_data,當「排序的鍵值對大小」 > max_length_for_sort_data 時,MySQL 認為磁碟外部排序的 IO 效率不如回表的效率,會選擇第一種排序模式;否則,會選擇第二種模式。第三種模式主要解決變長字符數據存儲空間浪費的問題。知識點二:優化器在估計符合條件的行數時有兩個選擇:

index diver:dive 到 index 中利用索引完成元組數的估算;特點是速度慢,但可以得到精確的值;

index statistics:使用索引的統計數值,進行估算;特點是速度快,但是值不一定準確。

總結

今天我們分享了 show profile 和 trace 的使用方法,我們來對比一下三種分析 SQL 方法的特點:

explain:獲取 MySQL 中 SQL 語句的執行計劃,比如語句是否使用了關聯查詢、是否使用了索引、掃描行數等;

profile:可以清楚了解到SQL到底慢在哪個環節;

trace:查看優化器如何選擇執行計劃,獲取每個可能的索引選擇的代價。

三種方法各有其適用場景,如果你有其它分析 SQL 的工具,歡迎在留言區分享。

最後推薦大家一款小米開源的sql分析工具:soar-web

你們的支持是我寫優質文章最大的動力,如果喜歡請關注我。謝謝

相關焦點

  • 使用explain和show profile來分析SQL語句實現優化SQL語句
    SQL語句優化是建立在慢查詢分析的基礎上,通過慢查詢定位有問題的SQL語句,關於慢查詢的介紹及其分析工具,可以參考[mysql慢查詢及慢查詢日誌分析工具]一、通過explain查詢1 用法:explain sql2 作用:用於分析sql語句(1)、id:執行explain的一個編號(沒有實際意義)(2)、
  • MySQL show profile使用說明
    show profile 和 show profiles 命令用於展示SQL語句的資源使用情況,包括CPU的使用,CPU上下文切換,IO等待,內存使用等,這個命令對於分析某個SQL的性能瓶頸非常有幫助,藉助於show profile的輸出信息,能讓我們知道一個SQL在哪個階段耗時最長,消耗資源最多
  • 《MySQL慢查詢優化》之SQL語句及索引優化
    1、慢查詢優化方式伺服器硬體升級優化Mysql伺服器軟體優化資料庫表結構優化SQL語句及索引優化>本文重點關注於SQL語句及索引優化,關於其他優化方式以及索引原理等,請關注本人《MySQL慢查詢優化》系列博文。
  • 一條查詢SQL在MySQL中是怎麼執行的
    也就是在創建表的時候,如果不指定存儲引擎類型,默認就是使用InnoDB,如果需要使用別的存儲引擎,在創建表的時候在create table語句中使用engine = MyISAM,來指定使用M有ISAM引擎創建表。不同的存儲引擎的表數據存取方式不同,支持的功能也不相同,以後我們再慢慢分析。
  • mysql常用命令,保存一下,以後查詢方便了
    -u root -pabc123 password ""5、root連接資料庫有密碼和無密碼mysql -u root(-uroot) -pmysql6、增加用戶test1密碼 abc,讓它可以在任何主機上登錄,並對所有資料庫有查詢
  • mysql大表中count()的用法以及mysql中count()的優化
    本篇文章給大家帶來的內容是關於mysql大表中count()的用法以及mysql中count()的優化,有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。一個單表中包含有6000w+的數據,然而你又不能拆分.需要分別統計表中有多少數據,A產品有多少,B產品有多少這幾個數據.
  • 京東面試:說說MySQL的架構體系
    雖然他搞java開發好幾年了,也一直使用的是MySQL資料庫,但是面對這個問題依然是一臉懵逼,還以為面試官要問索引、慢查詢、性能優化之類的(因為這些都是網上找點面試題背過了)。但這位面試官不按套路出牌,這位兄弟當場就是臉紅耳赤的,心想nnd居然會這麼問。其實面試中面試官的問題有千千萬,有的問題確實背背面試題就能應對,但不是所有的面試題咱們都能背下來的。
  • mysql 常用命令一
    >【資料庫SHOW命令】 顯示mysql中所有資料庫的名稱 show databases;#顯示mysql中的相關 show tables [ from db_name
  • 如何將 MySQL 去重操作優化到極致?|CSDN 博文精選
    外層查詢也要掃描t_source表的100萬行數據,在與導出表做連結時,對t_source表每行的item_id,使用auto_key0索引查找導出表中匹配的行,並在此時優化distinct操作,在找到第一個匹配的行後即停止查找同樣值的動作。
  • Python連接MySQL資料庫方法介紹(超詳細!手把手項目案例操作)
    作者 | CDA數據分析師 來源 | CDA數據分析研究院本文涉及到的開發環境:作業系統 Windows 10資料庫 MySQL 8.0>Python 3.7.2pip 19.0.3兩種方法進行資料庫的連接分別是PyMySQL和mysql.connector步驟:連接資料庫
  • 【MySQL】如何最大程度防止人為誤操作MySQL資料庫?
    指定別名 我們可以將操作MySQL的命令做成別名,防止他人和DBA誤操作資料庫,將操作MySQL的命令做成別名也非常簡單,這裡,我們直接上示例了,如下所示。[root@binghe~]# alias mysql='mysql -U'[root@binghe~]# mysql -uroot -poldboy123 -S /data/3306/mysql.sockWelcome to the MySQL monitor. Commands end with ; or \g.
  • 技術分享 | 用好 MySQL 的 MRR 優化器
    作者:蔣樂興MySQL DBA,擅長 python 和 SQL,目前維護著 github 的兩個開源項目:mysqltools 、
  • OpenResty、PHP-fpm與NodeJs操作MySQL的性能對比
    agentzh:我剛才在對比測試大結果集查詢時,發現NodeJS在使用 node-mysql庫訪問MySQL時,上下文切換次數居高不下,都快趕上 php-fpm + php-mysql了。但Node只起了一個進程,而且 strace 確認了確實是非阻塞的(不像 node-mysql-libmysqlclient 和 node-db-mysql 那樣濫用 OS 線程池玩阻塞通信),很是奇怪
  • 良心文章|MySQL性能優化分區之實戰(最全面最完整的分區)
    MySQL分區的有限主要包括以下4個方面:和單個磁碟或者文件系統分區相比,可以存儲更多數據優化查詢。在where子句中包含分區條件時,可以只掃描必要的一個或者多個分區來提高查詢效率;同時在涉及sum()和count()這類聚合函數的查詢時,可以容易的在每個分區上並行處理,最終只需要匯總所有分區得到的結果對於已經過期或者不需要保存的數據,可以通過刪除與這些數據有關的分區來快速刪除數據跨多個磁碟來分散數據查詢,以獲得更大的查詢吞吐量
  • MySQL資料庫常用命令詳解
    除了用第三方軟體管理MySQL資料庫外,MySQL本身也提供了管理資料庫的操作命令,可以在CentOS終端直接使用MySQL命令,用於MySQL資料庫的創建、表的管理、SQL查詢等管理操作。可以用show databases命令查看mydatabase資料庫是否被刪除。從圖3-47可以看出,mydatabase資料庫已被刪除。
  • mysql查詢資料庫導致中文亂碼
    mysql查詢資料庫,如果資料庫裡的欄位的值是中文,就會出現亂碼,怎麼解決呢?看下面的講解寫一個test.php的文檔,代碼如下所示,打開mysql的界面,新建一個xml的資料庫,再建一個student的數據表,欄位值和記錄如下圖所示,打開谷歌瀏覽器,運行test.php文檔。運行結果是下圖:看到了吧,出現亂碼了,怎麼辦呢?
  • 選擇pgsql還是mysql?
    概述:mysql出現在1994年,現在所有權歸屬oracle,創始人現在又發布了新的免費開源資料庫MariaDB,現在開源關係型資料庫領域,mysql使用確實是最廣泛的,官方說許多世界上最大、發展最快的組織都在使用mysql。pgsql又稱PostgresSQL,出現在1986年,官方標榜自己是世界上最先進最高級的開源關係型資料庫。
  • mysqldump的實現原理
    打開general logmysql> set global general_log=on;其中,general log的存放路徑可通過以下命令查看mysql> show variables like '%general_log_file%';
  • 程序開發必知必會的MySQL基本命令行操作
    就像學習Java語言初期要學習使用文本文檔編寫代碼並在命令提示符中運行一樣,雖然許多可視化軟體完全可以勝任,但學習在cmd中運行對Java的理解很有幫助。絕大多數的使用linux作業系統的大、中、小型網際網路網站都在使用mysql作為其後端資料庫存儲。
  • 一本徹底搞懂MySQL索引優化EXPLAIN百科全書
    今天我們來看下詳細看下優化器裡的執行計劃如何分析,要分析一個 SQL 的執行效率,就要會看執行計劃,根據執行計劃優化 SQL,使其能達到高效查詢的目的。一條查詢語句需要經過 MySQL 查詢優化器的各種基於成本和規則,優化後會生成一個所謂的執行計劃。