問題:性能下降SQL語句執行慢
問題表現:執行時間長、等待時間長
分析方法
- 觀察語句長時間的執行情況
- 開啓慢查詢日誌,設置閾值,將慢SQL抓取出來
- 通過Explain對慢SQL盡心分析
- 通過Show profile查看慢SQL執行的資源消耗情況
分析可能原因
- 查詢語句書寫問題
- 索引失效:創建索引但未使用
- 關聯查詢,使用太多的JOIN子句或者缺少索引
- SQL服務器各個參數設置問題1
簡單處理方案
性能分析專項可以查看後續博客內容
SQL執行順序
在書寫查詢語句時,首先要明確SQL語句在執行時的順序,適當的將篩選條件進行合理安排,可以有效地減少數據檢索範圍,提高檢索速度。
開發人員設計的SQL語句結構一般如下:
SELECT DISTINCT
<select_list>
FROM
<left_table>
<join_type> JOIN <right_table> ON <join_condition>
WHERE
<where_condition>
GROUP BY
<group_by_list>
HAVING
<having_condition>
ORDER BY
<order_by_condition>
LIMIT <limit_number>
MySQL執行語句時的順序如下:
1. FROM <left_table>
2. ON <join_condition>
3. <join_type > JOIN < right_table>
4. WHERE <where_condition>
5. ORDER BY <order_by_condition>
6. HAVING <having_condition>
7. SELECT
8. DISTINCT <select_list>
9. ORDER BY <order_by_condition>
10. LIMIT <limit_number>
使用Explain查看SQL語句執行計劃可以有助於優化SQL語句設計:Explain的使用
索引的使用
索引的定義
- MySQL官方對索引的定義:索引(Index)是幫助MySQL高效獲取數據的數據結構。
- 在數據之外,數據庫系統還維護着滿足特定查找算法的數據結構,這種數據結構通過實現高級查找算法引用(指向)數據,比如二叉樹查找,而這種數據結構就是索引。
- 開發人員平時所說的索引,如果沒有特別指明,都是指B-Tree(B樹,多路搜索樹,並不一定是二叉的)結構組織的索引。
- 一般來說索引本身也很大,不可能全部存儲在內存中,因此索引往往以索引文件的形式存儲在磁盤上。
索引的作用
索引可以在數據表中對添加索引的列值進行排序,形成類比字典索引的作用,這樣比如在某列中查詢“mysql”這個詞,就可以先定位到字母m,然後再在所有字母m開頭的值中找到第二位爲字母y的值,以此類推,不斷縮小檢索範圍,使得檢索效率提高。所以,索引也可以理解成“排好序的快速查找數據結構”。
索引的優勢
- 提高數據檢索的效率,降低數據庫的IO成本
- 降低數據排序的成本,降低CPU的消耗
索引的劣勢
- 索引佔用空間:索引實際上是一張保存了主鍵與索引字段的表,該表指向實體表的記錄
- 在對錶數據進行INSERT/UPDATE/DELETE時,MySQL不僅要跟新數據,還要對索引文件中添加了索引列的字段因爲更新造成的索引信息鍵值變化做出調整
- 索引只是提高效率的一個因素,如果存在大量數據的表,就需要花費大量時間研究建立最優化的索引,才能實現索引提高檢索效率的作用
索引的分類
- 單值索引:一個索引只包含一個列,一個表可以有多個單值索引
- 唯一索引:索引列的值必須唯一,但允許有空值
- 複合索引:一個索引包含多個列
基本語法
-- 創建
CREATE [UNIQUE] INDEX indexName ON tableName(column_list);
ALTER tableName ADD [UNIQUE] INDEX [indexName] ON (column_list);
-- 刪除
DROP INDEX [indexName] ON tableName;
-- 查看
SHOW INDEX FROM tableName;
索引的使用
- 主鍵自動建立唯一索引
- 頻繁作爲查詢條件的字段應該創建索引
- 查詢中與其他表關聯的字段(如外鍵)應該建立索引
- 相比於單值索引,更傾向於複合索引
- 查詢中排序的字段若與索引相符(字段順序),可以有效提高排序速度
- 查詢中統計或者分組字段2
- 頻繁更新的字段不適合創建索引
- where子句裏用不到的字段不創建索引
- 表記錄太少(百萬級以下)的數據表可以不創建
- 數據重複且分佈平均的表字段不創建索引(如性別字段),索引的選擇性3越接近於1,索引的效率越高
SQL中的JOIN查詢
其中,MySQL中不支持“FULL OUTER JOIN”的語法,可以通過下面的代碼實現這兩種情況的效果:
SELECT <select_list> FROM TableA A LEFT JOIN TableB B ON A.Key = B.Key
UNION
SELECT <select_list> FROM TableA A RIGHT JOIN TableB B ON A.Key = B.Key
SELECT <select_list> FROM TableA A LEFT JOIN TableB B ON A.Key = B.Key WHERE B.Key IS NULL
UNION
SELECT <select_list> FROM TableA A RIGHT JOIN TableB B ON A.Key = B.Key WHERE A.Key IS NULL