天天看點

(幹貨)MySQL 查詢性能優化以及SQL診斷調優原則、原理及思路

作者:架構師成長曆程

MySQL優化目标

✓減少磁盤IO

可從硬體,是否全表掃描,磁盤臨時表,日志、資料塊fsync,系統配置等方面着手

✓減少網絡帶寬

可從傳回太多資料,互動次數過多,庫表結構等方面考慮

✓降低CPU消耗

可從排序分組 order by, group by,SQL及索引,聚合函數:max,min,sum...等方面着手

優化流程及思路

關注的名額

➢CPU使用率

• sql查詢關鍵資源名額

• 資料掃描、顯式計算

➢IOPS

• 每秒io請求次數

• 實體讀寫關鍵資源名額

➢QPS/TPS

• 吞吐量

• 業務壓力

➢會話數/活躍會話數

• 應用配置

• 執行效率

➢Innodb邏輯讀/實體讀

• 反映整體查詢效率的引擎名額

➢臨時表

• 導緻SQL執行效率下降的特殊行為

(幹貨)MySQL 查詢性能優化以及SQL診斷調優原則、原理及思路

MySQL優化流程

建構完備的監控體系

• 細緻合理的告警

• 多元度圖形化名額

• 暴露性能缺陷,掌控大規模資源

分析定位問題

• 異常時間區間

定性分析

監控你的系

• System log、DB Error Log 統

• Slow Log

• SQL執行統計

• session

SQL優化原則與方法

原則

⚫減少通路量:資料存取是資料庫系統最核心功能,是以IO是資料庫系統中最容易出現性能瓶頸,減少SQL訪

問IO量是SQL優化的第一步;資料塊的邏輯讀也是産生CPU開銷的因素之一。

• 減少通路量的方法:建立合适的索引、減少不必通路的列、使用索引覆寫、語句改寫。

⚫減少計算操作:計算操作進行優化也是SQL優化的重要方向。SQL中排序、分組、多表連接配接操作等計算操作

都是CPU消耗的大戶。

• 減少SQL計算操作的方法:排序列加入索引、适當的列備援、SQL拆分、計算功能拆分。

方法

• 建立索引減少掃描量

• 調整索引減少計算量

• 索引覆寫(減少不必通路的列,避免回表查詢)

• SQL改寫

• 幹預執行計劃

原理剖析

(幹貨)MySQL 查詢性能優化以及SQL診斷調優原則、原理及思路

B+ Tree index

(幹貨)MySQL 查詢性能優化以及SQL診斷調優原則、原理及思路

MySQL SQL執行過程

1.客戶送出一條語句

2.先在查詢緩存檢視是否存在對應的緩存資料,如

有則直接傳回(一般有的可能性極小,是以一般建

議關閉查詢緩存)。

3.交給解析器處理,解析器會将送出的語句生成一

個解析樹。

4.預處理器會處了解析樹,形成新的解析樹。這一

階段存在一些SQL改寫的過程。

5.改寫後的解析樹送出給查詢優化器。查詢優化器

生成執行計劃。

6.執行計劃交由執行引擎調用存儲引擎接口,完成

執行過程。這裡要注意,MySQL的Server層和

Engine層是分離的。

7.最終的結果由執行引擎傳回給用戶端,如果開啟

查詢緩存的話,則會緩存。

MySQL SQL執行過程

SQL執行順序:

(8) SELECT (9) DISTINCT <select_list> (1) FROM <left_table> (3) <join_type> JOIN <right_table> (2) ON <join_condition> (4) WHERE <where_condition> (5) GROUP <group_by_list> (6) WITH {CUBE|ROLLUP}
(7) HAVING <having_condition> (10) ORDER BY <order_by_list> (11) LIMIT <limit_number> 18           

MySQL優化器與執行計劃

查詢優化器

⚫負責生成 SQL 語句的有效執行計劃的資料庫元件

⚫優化器是資料庫的核心價值所在,它是資料庫的“大腦”

⚫優化SQL,某種意義上就是了解優化器的行為

⚫優化的依據是執行成本(CBO)

⚫優化器工作的前提是了解資料,工作的目的是解析SQL,生成執行計劃

(幹貨)MySQL 查詢性能優化以及SQL診斷調優原則、原理及思路

MySQL優化器與執行計劃

查詢優化器工作過程

1.詞法分析、文法分析、語義檢查

2.預處理階段(查詢改寫等)

3.查詢優化階段(可詳細劃分為邏輯優化、物

理優化兩部分)

4.查詢優化器優化依據,來自于代價估算器估

算結果(它會調用統計資訊作為計算依據)

5.交由執行器執行

(幹貨)MySQL 查詢性能優化以及SQL診斷調優原則、原理及思路
(幹貨)MySQL 查詢性能優化以及SQL診斷調優原則、原理及思路

檢視和幹預執行計劃

執行計劃:

➢ explain [extended] SQL_Statement 優化器開關:

➢ show variables like 'optimizer_switch'

processlist

➢ show [full] processlist

➢ information_schema.processlist copy to tmp table:出現在某些alter table語句的copy table操作

Copying to tmp table on disk:由于臨時結果集大于tmp_table_size,正在将臨時表

從記憶體存儲轉為磁盤存儲以此節省記憶體

converting HEAP to MyISAM:線程正在轉換内部MEMORY臨時表到磁盤MyISAM臨

時表

Creating sort index:正在使用内部臨時表處理select查詢

Sorting index:磁盤排序操作的一個過程

Sending data :正在處理SELECT查詢的記錄,同時正在把結果發送給用戶端

Waiting for table metadata lock: 等待中繼資料鎖

...

正常優化政策

SELECT優化-order by

order by查詢的兩種情況:

• Using index。MySQL直接通過索引傳回有序記錄,不需要額外的排序操作,操作效率較高

• Using filesort。無法隻通過索引擷取有序結果集,需要額外的排序,某些特殊情況下,會出現

Using temporary

優化目标:盡量通過索引來避免額外的排序,減少CPU資源的消耗

✓where條件和order by使用相同的索引

✓order by的順序和索引順序相同

✓order by的字段同為升序或降序

注:當where條件中的過濾字段為覆寫索引的字首列,而order by字段是第二個索引列時,隻有

where條件是const比對時,才可以通過索引消除排序,而between...and或>?、<?這種range比對

都無法避免filesort操作

SELECT優化-order by

當無法避免filesort操作時,優化思路就是讓filesort的操作更快

排序算法:

• 兩次掃描算法。兩次通路資料,第一步擷取排序字段的行指針資訊,在記憶體中排序,第二步根據

行指針擷取記錄

• 一次掃描算法。一次性取出滿足條件的所有記錄,在排序區中排序後輸出結果集。是采用空間換

時間的方式

注:需要排序的字段總長度越小,越趨向于第二種掃描算法,MySQL通過

max_length_for_sort_data參數的值來進行參考選擇

優化政策:

1、适當調大max_length_for_sort_data這個參數的值,讓優化器更傾向于選擇第二種掃描算法

2、隻使用必要的字段,不要使用select *的寫法

3、适當加大sort_buffer_size這個參數的值,避免磁盤排序的出現(線程參數,不要設定過大)

SELECT優化-Subquery

➢子查詢會用到臨時表,需盡量避免

➢可以使用效率更高的join查詢來替代

優化政策:

等價改寫、反嵌套

如下SQL:

select * from customer where customer_id not in (select customer_id from payment)           

改寫形式:

select * from customer a left join payment b on a.customer_id=b.customer_id where b.customer_id is null 26           

SELECT優化-limit

➢分頁查詢,就是将過多的結果在有限的界面上分好多頁來顯示。

➢其實質是每次查詢隻傳回有限行,翻頁一次執行一次。

優化目标:

1、消除排序

2、避免掃描到大量不需要的記錄

SQL場景(film_id為主鍵):

select film_id,description from film order by title limit 10000,20           

此時MySQL排序出前10020條記錄後僅僅需要傳回第10001到10020條記錄,前

10000條記錄造成額外的代價消耗

SELECT優化-limit

優化政策一:

覆寫索引

alter table film add index idx_lmtest(title,description);           

• 記錄直接從索引中擷取,效率最高

• 僅适合查詢字段較少的情況

優化政策二:

SQL改寫

select a.film_id,a.description from film a inner join (select film_id from film order by title limit 1000,20) b on a.film_id=b.film_id;           

• 優化的前提是title字段有索引

• 思路是從索引中取出20條滿足條件記錄的主鍵值,然後回表擷取記錄

SELECT優化-or/and condition

• and結果集為關鍵字前後過濾結果的交集

• or結果集為關鍵字前後分别查詢的并集

OR

• and條件可以在前一個條件過濾基礎上過濾

• or條件被處理為UNION,相當于兩個單獨條件的查詢

• 複合索引對于or條件相當于一個單列索引

處理政策:

✓and子句多個條件中擁有一個過濾性較高的索引即可

✓or條件前後字段均要建立索引

✓為最常用的and組合條件建立複合索引

(幹貨)MySQL 查詢性能優化以及SQL診斷調優原則、原理及思路
(幹貨)MySQL 查詢性能優化以及SQL診斷調優原則、原理及思路

join優化

• Nested-Loop Join算法
for each row in t1 matching range {
for each row in t2 matching reference key {
for each row in t3 {
if row satisfies join conditions, send to client
}
}
}           

• 關聯字段索引:每層内部循環僅擷取需要關心的資料

• 引申算法:Bloack Nested-Loop

• 小表驅動原則:減少循環次數

• 小表:傳回結果集較少的表

(幹貨)MySQL 查詢性能優化以及SQL診斷調優原則、原理及思路

join優化

• 關聯字段索引的必要性

(幹貨)MySQL 查詢性能優化以及SQL診斷調優原則、原理及思路
(幹貨)MySQL 查詢性能優化以及SQL診斷調優原則、原理及思路

join優化

• 小表驅動原則

忽略b表的索引,使b表作為驅動表:

(幹貨)MySQL 查詢性能優化以及SQL診斷調優原則、原理及思路
(幹貨)MySQL 查詢性能優化以及SQL診斷調優原則、原理及思路

忽略a表的索引,使a表作為驅動表:

insert優化

優化政策一:

減少互動次數

如批量插入語句:

insert into test values(1,2,3); insert into test values(4,5,6); insert into test values(7,8,9);           

可改寫為如下形式:

insert into test values(1,2,3),(4,5,6),(7,8,9) ...;            

優化政策二:

文本裝載方式

通過LOAD DATA INFILE句式,從文本裝載資料,通常比insert語句快20倍

06 小結

MySQL查詢優化

✓優化的目的是讓資源發揮價值

✓SQL和索引是調優的關鍵,往往可以起到“四兩撥千斤”的效果

✓充分了解核心名額,并建構完備的監控體系,這是優化工作的前提

✓SQL優化的原則是減少資料通路及計算

✓常用的優化方法主要是調整索引、改寫SQL、幹預執行計劃

✓innodb的表是典型的IOT,資料本身是B+ tree索引的葉節點

✓掃描二級索引可以直接擷取資料,或者傳回主鍵id

✓優化器是資料庫的大腦,我們要了解優化器,并觀測以及幹預MySQL的行為

繼續閱讀