sql 語句性能分析
1、看 sql 語句執行時間
2、看 sql 的執行計划
3、查看 sql 的執行中各個環節耗時時間
4、查看mysql的執行進程,處理鎖表的情況,命令 show PROCESSLIST, state 為LOCKED,說明產生鎖表,ID為進程id,直接執行kill ID,就可以停止這個進程;
MySQL整個查詢執行過程:
1、客戶端同數據庫服務層建立TCP連接。
2、客戶端向MySQL服務器發送一條查詢請求。
3、連接線程接收到SQL語句之后,將語句交給SQL語句解析模塊進行語法分析和語義分析。
4、先看查詢緩存中是否有結果,如果有結果可以直接返回給客戶端。
5、如果查詢緩存中沒有結果,就需要真的查詢數據庫引擎層了,於是發給SQL優化器,進行查詢的優化,生成相應的執行計划。
6、MySQL根據執行計划,調用存儲引擎的API來執行查詢
7、使用存儲引擎查詢時,先打開表,如果需要的話獲取相應的鎖。 查詢緩存頁中有沒有相應的數據,如果有則可以直接返回,如果沒有就要從磁盤上去讀取。
8、當在磁盤中找到相應的數據之后,則會加載到緩存中來,從而使得后面的查詢更加高效,由於內存有限,多采用變通的LRU表來管理緩存頁,保證緩存的都是經常訪問的數據。
9、最后,獲取數據后返回給客戶端,關閉連接,釋放連接線程。
Procedure Analyse優化表結構
PROCEDURE ANALYSE() ,在優化表結構時可以輔助參考分析語句。通過分析select查詢結果對現有的表的每一列給出優化的建議。
利用此語句,MySQL 幫你去分析你的字段和其實際的數據,並會給你一些有用的建議。
【只有表中有實際的數據,這些建議才會變得有用,因為要做一些大的決定是需要有數據作為基礎的。】
PROCEDURE ANALYSE的語法如下:
SELECT ... FROM ... WHERE ... PROCEDURE ANALYSE([max_elements,[max_memory]])
max_elements:指定每列非重復值的最大值,當超過這個值的時候,MySQL不會推薦enum類型。(默認值256)
max_memory (默認值8192)analyse()為每列找出所有非重復值所采用的最大內存大小。
執行返回中的Optimal_fieldtype列是mysql建議采用的列。
樣例程序
mysql> DESC user_account;
+-----------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+------------------+------+-----+---------+----------------+
| USERID | int(10) unsigned | NO | PRI | NULL | auto_increment |
| USERNAME | varchar(10) | NO | | NULL | |
| PASSSWORD | varchar(30) | NO | | NULL | |
| GROUPNAME | varchar(10) | YES | | NULL | |
+-----------+------------------+------+-----+---------+----------------+
rows in set (0.00 sec)
mysql> select * from user_account PROCEDURE ANALYSE(1)\G;
*************************** 1. row ***************************
Field_name: ibatis.user_account.USERID
Min_value: 1
Max_value: 103
Min_length: 1
Max_length: 3
Empties_or_zeros: 0
Nulls: 0
Avg_value_or_avg_length: 51.7500
Std: 50.2562
Optimal_fieldtype: TINYINT(3) UNSIGNED NOT NULL
*************************** 2. row ***************************
Field_name: ibatis.user_account.USERNAME
Min_value: dfsa
Max_value: LMEADORS
.........................................................
從第一行輸出我們可以看到analyze分析ibatis.user_account.USERID列
最小值1,最大值103,最小長度1,最大長度3,字符串或0的個數為0;值為空的字段數為0;平均每個字段的值為51.7500
並給出了該字段的優化建議:建議將該字段的數據類型改成TINYINT(3) UNSIGNED NOT NULL。
查詢語句出現sending data耗時解決
執行SHOW PROFILES 查出Query_ID后在執行 show profile for query Query_ID ,或者是show processlist,查看查詢所耗時資源
得知查詢到語句耗時主要集中在 sending data上
解決步驟:
1、查詢資料需要開啟查詢緩存,執行命令查看開啟情況 show variables like '%query_cache%',No則是未開啟,改配置文件設置 query_cache_type=YES后重啟
2、查看buffer 執行 show variables like 'innodb_buffer_pool%',可以看出innodb_buffer_pool_size只有8M大小
這里設置成3G,SET GLOBAL innodb_buffer_pool_size = 3221225472,然后重啟mysql(參考:https://www.cnblogs.com/wanbin/p/9530833.html)
3、查看表索引,show index from table_name發現cardinality的值為1,表的cardinality(可以翻譯為“散列程度”),它表示某個索引對應的列包含多少個不同的值。如果cardinality大大少於數據的實際散列程度,那么索引就基本失效了。
使用命令:analyze table table_name修復索引,如果修復失敗,查看是否因為新添加的字段設置了相同的默認值
總結
從上面這個例子我們可以看出analyze能根據目前表中的數據情況給出優化建議。當數據庫在生產環境運行一定時間以后,開發或是DBA能參考analyze的分析結果來對表結構做出一定的優化。
參考:
1、Navicat常用功能:https://blog.csdn.net/littlexiaoshuishui/article/details/82884094
2、MySQL查詢過程剖析:https://blog.csdn.net/z_ryan/article/details/82262761
3、分析診斷工具之Procedure Analyse:https://www.cnblogs.com/duanxz/p/3968639.html
4、sending data耗時解決:https://www.cnblogs.com/yaoxing92/p/11058420.html、https://www.cnblogs.com/rwxwsblog/p/5684213.html