必須掌握 MySQL查詢優化

2021-10-10 17:25:51 字數 4755 閱讀 8455

開啟慢查詢日誌

檢視 mysql 資料庫是否開啟了慢查詢日誌和慢查詢日誌檔案的儲存位置的命令如下:

show variables like 'slow_query_log%'
通過如下命令開啟慢查詢日誌:

set global slow_query_log = on; 

set global slow_query_log_file =

'oak-slow.log'

; set global log_queries_not_using_indexes = on;

set long_query_time =

10;

long_query_time:指定慢查詢的閥值,單位秒。如果sql執行時間超過閥值,就屬於慢查詢記錄到日誌檔案中。

log_queries_not_using_indexes:表示會記錄沒有使用索引的查詢sql。前提是slow_query_log的值為on,否則不會奏效。

檢視慢查詢日誌

文字方式檢視

直接使用文字編輯器開啟slow.log日誌即可。

time:日誌記錄的時間

user@host:執行的使用者及主機

query_time:執行的時間

lock_time:鎖表時間

rows_sent:傳送給請求方的記錄數,結果數量

rows_examined:語句掃瞄的記錄條數

set timestamp:語句執行的時間點

select...

.:執行的具體的sql語句

使用mysqldumpslow檢視

mysql 提供了乙個慢查詢日誌分析工具mysqldumpslow,可以通過該工具分析慢查詢日誌

內容。在 mysql bin目錄下執行下面命令可以檢視該使用格式。

perl mysqldumpslow.pl --help
執行如下命令檢視慢查詢日誌資訊:

perl mysqldumpslow.pl -t 5

-s at c:\programdata\mysql\data\oak-slow.log

除了使用mysqldumpslow工具,也可以使用第三方分析工具,比如pt-query-digest、mysqlsla等

索引和慢查詢

如何判斷是否為慢查詢?

mysql判斷一條語句是否為慢查詢語句,主要依據sql語句的執行時間,

它把當前語句的執行時間跟 long_query_time 引數做比較,如果語句的執行時間 >

long_query_time,就會把這條執行語句記錄到慢查詢日誌裡面。

long_query_time 引數的預設值是 10s,該引數值可以根據自己的業務需要進行調整。

如何判斷是否應用了索引?

sql語句是否使用了索引,可根據sql語句執行過程中有沒有用到表的索引,

可通過 explain命令分析檢視,檢查結果中的 key 值,是否為null。

應用了索引是否一定快?

下面我們來看看下面語句的 explain 的結果,你覺得這條語句有用上索引嗎?比如

select * from user where id>

0;

雖然使用了索引,但是還是從主鍵索引的最左邊的葉節點開始向右掃瞄整個索引樹,進行了全表掃瞄,此時索引就失去了意義。

而像 select * from user where id = 2; 這樣的語句,才是我們平時說的使用了索引。它表示的意思是,我們使用了索引的快速搜尋功能,並且有效地減少了掃瞄行數。

我們在使用索引時,不要只關注是否起作用,應該關心索引是否減少了查詢掃瞄的資料行數,如果掃瞄行數減少了,效率才會得到提公升。對於乙個大表,不止要建立索引,還要考慮索引過濾性,過濾性好,執行速度才會快。

提高索引過濾性

假如有乙個5000萬記錄的使用者表,通過***='男』索引過濾後,還需要定位3000萬,sql執行速度也不會很快。其實這個問題涉及到索引的過濾性,比如1萬條記錄利用索引過濾後定位10條、100條、1000條,那他們過濾性是不同的。索引過濾性與索引字段、表的資料量、表設計結構都有關係。

下面我們看乙個案例:

表:student 

字段:id,name,***,age

造資料:insert into student (name,***,age) select name,***,age from student;

sql案例:select * from student where age=

18 and name like '張%'

;(全表掃 描)

優化1

alter table student add index

(name)

;//追加name索引

優化2

alter table student add index

(age,name)

;//追加age,name索引

優化3

可以看到,index condition pushdown 優化的效果還是很不錯的。

再進一步優化,我們可以把名 字的第乙個字和年齡做乙個聯合索引,

這裡可以使用 mysql 5.7 引入的虛擬列來實現。

//為user表新增first_name虛擬列,以及聯合索引(first_name,age)

alter table student add first_name varchar(2

) generated always as (

left

(name,1)

), add index

(first_name, age)

; explain select * from student where first_name=

'張' and age=

18;

慢查詢原因總結

全表掃瞄:explain分析type屬性all

全索引掃瞄:explain分析type屬性index

索引過濾性不好:靠索引字段選型、資料量和狀態、表設計

頻繁的回表查詢開銷:盡量少用select *,使用覆蓋索引

一般性分頁

般的分頁查詢使用簡單的 limit 子句就可以實現。limit格式如下:

select * from 表名 limit [offset,

] rows

第乙個引數指定第乙個返回記錄行的偏移量,注意從0開始;

第二個引數指定返回記錄行的最大數目;

如果只給定乙個引數,它表示返回最大的記錄行數目;

思考1:如果偏移量固定,返回記錄量對執行時間有什麼影響?

select * from user limit 10000,1

;select * from user limit 10000,10

;select * from user limit 10000

,100

; select * from user limit 10000

,1000

; select * from user limit 10000

,10000

;

結果:在查詢記錄時,返回記錄量低於100條,查詢時間基本沒有變化,差距不大。隨著查詢記錄量越大,所花費的時間也會越來越多。

思考2:如果查詢偏移量變化,返回記錄數固定對執行時間有什麼影響?

select * from user limit 1

,100

; select * from user limit 10

,100

; select * from user limit 100

,100

; select * from user limit 1000

,100

; select * from user limit 10000

,100

;

結果:在查詢記錄時,如果查詢記錄量相同,偏移量超過100後就開始隨著偏移量增大,查詢時間急劇的增加。(這種分頁查詢機制,每次都會從資料庫第一條記錄開始掃瞄,越往後查詢越慢,而且查詢的資料越多,也會拖慢總查詢速度。)

分頁優化方案

第一步:利用覆蓋索引優化

*

*select * from user limit 10000

,100

; select id from user limit 10000

,100;*

*

第二步:利用子查詢優化

select * from user limit 10000

,100

; select * from user where id>=

(select id from user limit 10000,1

) limit 100

;

原因:使用了id做主鍵比較(id>=),並且子查詢使用了覆蓋索引進行優化。

必須掌握 MySQL索引原理

mysql官方對索引定義 是儲存引擎用於快速查詢記錄的一種資料結構。需要額外開闢空間和資料維護工作。索引是物理資料頁儲存,在資料檔案中 innodb,ibd檔案 利用資料頁 page 儲存。索引可以加快檢索速度,但是同時也會降低增刪改操作速度,索引維護需要代價。索引涉及的理論知識 二分查詢法 has...

必須掌握的13種SQL語句優化

1 對查詢進行優化,應盡量避免全表掃瞄,首先應考慮在where 及order by 涉及的列上建立索引。2 應盡量避免在where 子句中使用 或 操作符,否則引擎放棄使用索引而進行全表掃瞄。3 應盡量避免在where 子句中對字段進行 null值判斷。否則將導致引擎放棄使用索引而進行全表掃瞄,如 ...

查詢優化(MySQL優化查詢)

關聯查詢太多join 設計缺陷或不得已的需求 資料庫伺服器調優及各個引數設定不適當 緩衝 執行緒數等 慢查詢日誌 找出執行速度慢的sql語句 慢查詢的開啟並捕獲 explain 慢sql分析 show profile查詢sql在mysql伺服器裡面的執行細節和生命週期情況 sql資料庫伺服器的引數調...