MySQL(二) —— MySQL效能優化之 SQL語句優化
SQL語句優化
MySQL優化的目的
1、避免出現頁面訪問錯誤:或由於資料庫連線超時 timeout 產生頁面5xx錯誤;或由於慢查詢造成頁面無法載入;或由於阻 塞造成資料無法提交;
2、增加資料庫的穩定性:避免由於低效查詢引起的資料庫問題;
3、優化使用者體驗:提高頁面訪問的流暢度。
一、SQL語句優化
1、使用EXPLAIN關鍵字檢測SELECT查詢,查詢SQL的執行計劃。
舉例:
EXPLAIN SELECT COUNT(1) FROM account.user_info WHERE channel='mmo_no_platform' AND serverid='5020' AND id>=8;
mysql> EXPLAIN SELECT COUNT(1) FROM account.user_info WHERE channel='mmo_no_platform' AND serverid='5020' AND id>=8; +----+-------------+-----------+-------------+--------------------------+------------------+---------+------+------+-------------------------------------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-----------+-------------+--------------------------+------------------+---------+------+------+-------------------------------------------------------------+ | 1 | SIMPLE | user_info | index_merge | PRIMARY,channel,serverid | serverid,channel | 9,391 | NULL | 56 | Using intersect(serverid,channel); Using where; Using index | +----+-------------+-----------+-------------+--------------------------+------------------+---------+------+------+-------------------------------------------------------------+ 1 row in set (0.00 sec)
explain 查詢結果分析:
select_type:查詢型別
table:查詢的表
type:連線的型別。好→差:const、eq_reg、ref、range、index、ALL。
possible_keys:可能使用到的索引。若為NULL,則無可能索引;
key:實際使用的索引(主鍵)。若為NULL,則無使用索引;
key_len:使用的索引的長度。在不損失精確性的情況下,索引長度越短越好。
ref:被使用的索引的列,可能是一個常數
rows:MySQL認為必須檢查的用來返回請求資料的行數
Extra:當有 使用檔案排序 Using filesort 或者 使用臨時表 Using temporary 時,則需要優化。
Count() 和MAX() 的優化方法
Count(*)和Count(id)的區別:Count(*)會計入id=NULL的行數,得到的結果可能會比Count(id)的值大。
mysql> EXPLAIN SELECT MAX(createdate) FROM account.user_info;
mysql> EXPLAIN SELECT MAX(createdate) FROM account.user_info;
+----+-------------+-----------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+------+---------------+------+---------+------+------+-------+
| 1 | SIMPLE | user_info | ALL | NULL | NULL | NULL | NULL | 18828 | NULL |
+----+-------------+-----------+------+---------------+------+---------+------+------+-------+
1 row in set (0.00 sec)
mysql> SELECT MAX(createdate) FROM account.user_info;
+---------------------+
| MAX(createdate) |
+---------------------+
| 2018-11-01 14:34:39 |
+---------------------+
1 row in set (0.00 sec)
建立索引:mysql> create index createdate on account.user_info(createdate);
mysql> CREATE INDEX createdate on account.user_info(createdate);
Query OK, 0 rows affected (0.26 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> EXPLAIN SELECT MAX(createdate) FROM account.user_info;
+----+-------------+-------+------+---------------+------+---------+------+------+------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+------------------------------+
| 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | Select tables optimized away |
+----+-------------+-------+------+---------------+------+---------+------+------+------------------------------+
1 row in set (0.01 sec)
子查詢的優化:
通常情況下,需要把子查詢優化為 join 連線查詢,但在優化時要注意關聯鍵是否有一對多的關係,要注意重複資料。可以使用distinct 關鍵字進行去重查詢。
group by 查詢的優化:避免出現使用檔案排序 Using filesort 或者 使用臨時表 Using temporary 的情況。在子查詢內部增加過濾條件,而不是在外部加過濾條件group by。
LIMIT查詢的優化:limit 常用於分頁處理,時常會伴隨Order By從句使用,因此大多時候會使用 file sorts ,這樣會造成大量的IO問題。優化方式1、使用主鍵或有索引的列進行Order By 操作;2、當只要一行資料時使用LIMIT 1
使用連線(JOIN)來代替子查詢(Sub-Queries)
MySQL從4.1開始支援SQL的子查詢。這個技術可以使用SELECT語句來建立一個單列的查詢結果,然後把這個結果作為過濾條件用在另一個查詢中。例如,我們要將客戶基本資訊表中沒有任何訂單的客戶刪除掉,就可以利用子查詢先從銷售資訊表中將所有發出訂單的客戶ID取出來,然後將結果傳遞給主查詢,如下所示:
1、使用EXPLAIN關鍵字檢測SELECT查詢,查詢SQL的執行計劃。
2、使用查詢快取優化查詢
3、當只要一行資料時使用LIMIT 1
4、為搜尋欄位建立索引
5、在join表的時候使用相當型別的列,並將其索引
6、切記不要使用ORDER BY RAND()
7、避免使用SELECT *
8、永遠為每張表設定一個ID主鍵
9、使用ENUM而不是VARCHAR
10、儘可能的不要賦值為NULL
11、固定長度的表會更快
12、垂直分割
13、拆分大的DELETE或INSERT
14、越小的列會越快
15、選擇正確的儲存引擎
16、小心永久連結