<p>SQL 語句優化</p>
MySQL 的優化主要指 SQL 語句的優化和 MySQL Server 的優化,相對來說,SQL 優化相對更為重要,也更考驗功力。本小節將講解 SQL 語句優化的一般思路,以及相應方法。
1. SQL優化的一般步驟
當碰到一個存在效能問題的 MySQL 資料庫時,一般按照如下步驟進行分析解決:
- 定位問題 SQL;
- 分析 SQL 執行計劃;
- 分析 SQL Profile;
- 實施優化措施。
2. 定位問題SQL
定位 MySQL 的問題 SQL,主要有兩種方法,檢視當前執行緒(show processlist)和慢日誌。一般來說,當前發生的問題用到 show processlit,事後分析用到慢日誌。
2.1 檢視當前執行緒
通過 show processlist 命令檢視當前正在執行的sql語句,包括執行狀態,是否鎖表,執行時長等。
mysql> show processlist\G
*************************** 1. row ***************************
Id: 5866557
User: root
Host: localhost
db: tempdb
Command: Query
Time: 0
State: starting
Info: show processlist
**** *********************** 2. row ***************************
Id: 5866711
User: root
Host: localhost
db: tempdb
Command: Query
Time: 1
State: starting
Info: select * from customer where balance=10;
2 rows in set (0.00 sec)
有時 SQL 語句比較複雜,而且執行量較大,通過 show processlist 來檢視不太方便,這時可以通過表information_schema.processlist 進行檢視,還可以自定義查詢方式。
mysql> select * from information_schema.processlist order by info desc\G
*************************** 1. row ***************************
ID: 5866557
USER: root
HOST: localhost
DB: tempdb
COMMAND: Query
TIME: 0
STATE: executing
INFO: select * from information_schema.processlist order by info desc
*************************** 2. row ***************************
ID: 5866711
USER: root
HOST: localhost
DB: tempdb
COMMAND: Sleep
TIME: 261
STATE:
INFO: NULL
2 rows in set (0.00 sec)
2.2 慢日誌
通過分析慢日誌定位儲存效能問題的 SQL,慢日誌有一個閾值引數 long_query_time,單位是秒,比如該引數設定為 1,那麼執行時長超過 1 秒的 SQL 都會被記錄到慢日誌檔案:
想要快速分析慢日誌的 SQL,建議使用 percona 公司的慢日誌分析工具 pt-query-digest。
3. 分析 SQL 執行計劃
找到問題 SQL 後,通過 explain 命令檢視執行計劃:
mysql> explain select * from customer where balance=10\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: customer
partitions: NULL
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 20965
Extra: Using where
1 row in set, 1 warning (0.00 sec)
其中 select_type 表示 select 型別,一般值為 simple、primary、union、subquery。type 表示訪問型別,常見值有(效能由差到好):ALL、index、range、ref、eq_ref、const:
- type 等於 ALL,表示全表掃描,需要遍歷全表所有的資料;
- type 等於 index,表示索引全掃描,需要遍歷整個索引來查詢需要的資料;
- type 等於 range,表示索引範圍掃描,掃描索引部分資料即可查詢需要的資料,常見操作有大於、小於、between;
- type 等於 ref,使用唯一或非唯一索引的字首掃描,返回查詢到的單獨值;
- type 等於 eq_ref,使用唯一索引,且僅有一條記錄匹配;
- type 等於 const,表中僅有一行資料是匹配的。
4. 分析 SQL Profile
想要進一步分析 SQL,可以通過 show profiles 命令:
mysql> select * from customer where balance=10;
mysql> show profiles;
+----------+------------+-----------------------------------------+
| Query_ID | Duration | Query |
+----------+------------+-----------------------------------------+
| 1 | 0.00015800 | select @@profiling |
| 2 | 0.00017150 | SELECT DATABASE() |
| 3 | 0.00512225 | select * from customer where balance=10 |
+----------+------------+-----------------------------------------+
3 rows in set, 1 warning (0.00 sec)
mysql> show profile for query 3;
+----------------------+----------+
| Status | Duration |
+----------------------+----------+
| starting | 0.000083 |
| checking permissions | 0.000014 |
| Opening tables | 0.000032 |
| init | 0.000042 |
| System lock | 0.000010 |
| optimizing | 0.000010 |
| statistics | 0.000017 |
| preparing | 0.000013 |
| executing | 0.000002 |
| Sending data | 0.003163 |
| end | 0.000003 |
| query end | 0.000007 |
| closing tables | 0.000007 |
| freeing items | 0.000105 |
| cleaning up | 0.000015 |
+----------------------+----------+
15 rows in set, 1 warning (0.00 sec)
show profile for query 可以看出這條 SQL 執行過程中的步驟和相應消耗時間,從執行結果可以看到,Sending data 這個狀態是耗時最長的。
5. 實施優化措施
我們找到問題 SQL,並分析原因後,就得采取相應措施進行優化,以提高 SQL 語句的執行效率。
在分析 SQL 執行計劃這一小節的例子中,我們可以看到執行計劃是 type 等於 ALL,表示需要對錶customer 進行全表掃描才能找到相應資料,這時我們要對欄位 balance 增加索引。
mysql> alter table customer add index idx_balance(balance);
Query OK, 0 rows affected (0.15 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> explain select * from customer where balance=10\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: customer
partitions: NULL
type: ref
possible_keys: idx_balance
key: idx_balance
key_len: 6
ref: const
rows: 10
Extra: NULL
1 row in set, 1 warning (0.00 sec)
從執行計劃,可以看出,掃描行數從20965行減少至10行,查詢效率可以大大提升。
6. 小結
本小節主要介紹了 SQL 語句優化的一般思路以及相應方法。
請記住以下優化 SQL 的步驟和方法,熟練掌握後,在一定程度上可以提高工作效率。
- 定位問題 SQL;
- 分析 SQL 執行計劃;
- 分析 SQL Profile;
- 實施優化措施。