mysql查詢效能優化 MySQL 查詢效能優化

2021-10-17 23:44:19 字數 3149 閱讀 4597

在日常開發中,程式設計師寫的最多的除了bug之外,應該算是sql語句了。sql的質量影響了程式的響應速度,只有利用mysql的特性,才能讓mysql更有效的執行查詢sql,充分發揮mysql的優勢,並避開它的弱點。

為什麼查詢速度會慢?

在編寫sql之前,需要清楚一點 -- 真正重要的是響應時間。

如果我們把查詢看作是乙個任務,那麼它由一系列子任務組成,每個子任務都會消耗一定的時間。如果要優化查詢,就是要優化其子任務,要麼消除其中的一些子任務,要麼減少子任務的執行次數。

慢查詢通過開啟mysql中的慢查詢,可以明確的掌握系統中有哪些sql查詢在影響整個系統的效能,從而更準確的去針對這些sql進行優化。

查詢慢查詢開啟狀態--on/off

show variables like 'slow_query%';

開啟慢查詢日誌

set global slow_query_log='on';

show variables like 'long_query_time';

設定查詢超時(10s)記錄

set global long_query_time=10;

查詢效能低,最基本的原因是訪問的資料太多。某些查詢可能不可避免的需要篩選大量資料,但大部分效能低下的查詢都可以通過減少訪問的資料量的方式進行優化。

使用limit對查詢資料進行限制

開發者通常會誤以為mysql只會返回需要的資料(例如select 取出100條記錄,只在頁面顯示前20條記錄),實際上mysql卻是先返回全部結果集後再進行計算。最簡單有效的解決方法就是在查詢後面加上limit。

多表關聯查詢只取需要的列

例:查詢所有在電影《七宗罪》中的演員

select * from actor inner join filmactor using(actorid) inner join film using(film_id) where

film.title='se7en';

上述sql將返回這三個表的全部資料列。正確的開啟方式應該如下只取需要的列:

select actor.* from actor...

看到select *的時候都需要用懷疑的眼光審視

select *會取出全部列,這樣會讓優化器無法完成索引覆蓋掃瞄這列優化,還會為伺服器帶來額外的i/o、記憶體和cpu的消耗。因此專案組都會嚴格禁止select *的寫法。

合理使用快取

當程式出現不斷重複執行相同的查詢sql,然後每次返回的結果都一樣的情況,作為一名合格的程式設計師,你應該考慮到將初次查詢的結果集快取起來。如果查詢快取是開啟的,mysql會優先檢查這個查詢是否命中快取中的資料。這個檢查是通乙個對大小寫敏感的雜湊查詢實現的。查詢和快取中的查詢即使只有乙個位元組不同,那也不會匹配快取結果。若當前的查詢恰好命中快取且使用者許可權沒有問題,那麼mysql會跳過所有其他階段,直接衝快取中拿到結果並返回給客戶端。

查詢優化器

經過mysql優化器選擇的執行計畫並不一定是最快的執行方式。

下面是一些mysql能夠處理的優化型別:重新定義關聯表的順序

將外連線轉化成內連線

使用等價變換規則:mysql可以使用一些等價變換來簡化並規範表示式。例,(5=5 and a>5)將被改寫為a>5。

優化count(),min()和 max():索引和列是否可為空通常可以幫助mysql優化這類表示式。例如,找某列的最小值,只需要查詢b-tree索引的最左端的記錄。

覆蓋索引掃瞄:當索引中的列包含所有查詢中需要使用的列的時候,mysql就可以使用索引返回所需的資料,而無需查詢對應的資料行。

提前終止查詢

列表in()的比較:mysql將in()列表中的資料先進行排序,然後通過二分法查詢的方式來確定列表中的值是否滿足條件,這是乙個o(log n)複雜度的操作,等價的轉換成or查詢的複雜度為o(n),對於in()列表中有大量取值的時候,mysql的處理速度將會更快。

高效利用索引覆蓋索引:如果乙個索引包含所有需要查詢的字段值,就稱之為覆蓋索引我們通常會根據where條件來建立合適的索引,mysql可以使用索引來直接獲取列的資料。如果索引中的葉子節點已經包含要查詢的資料,就沒有必要回表查詢了,減少i/o提高效率。

索引的最左字首匹配:查詢語句使用like時,應使用key%,避免全表掃瞄。select ...from xx where col like 'key%';

使用使用者自定義變數

使用者自定義變數是乙個很容易被忽略的mysql特性,但是如果能夠用好,發揮其潛力在某些場景下可以寫出非常高效的查詢語句

使用者自定義變數是乙個用來儲存內容的臨時容器,可使用set和select語句來定義:

set @one:=1;

set @min_actor:=(select min(actor_id) from actor);

set @last_week:=current_date - interval 1 week;

可以在任意可以使用表示式的地方使用自定義變數.

select ... where col <= @last_week;

一下場景不能使用使用者自定義變數:使用自定義變數的查詢,無法使用查詢快取

不能在使用常量或識別符號的地方使用自定義變數,例如表名,列名,limit子句中

使用者自定義變數的生命週期是在乙個連線中生效,所以不能用他們來做連線間的通訊

mysql優化器在某些場景下可能會將這些變數優化掉

賦值符號:=的優先順序非常低,所以需要注意 賦值表示式應該使用明確的括號

使用自定義變數示例:

#實現對電影演員演出場次的排名

#只有當前演員參演的電影數量和前乙個演員不同時排名才會發生變化

#使用三個變數分別儲存當前的排名,前乙個演員的排名,當前演員參演的電影數量

set @curr_cnt := 0,@prev_cnt := 0,@rank :=0;

select actor_id,

@curr_cnt := cnt as cnt,

@rank := if(@prev_cnt <> @curr_cnt,@rank + 1,@rank) as rank,

@prev_cnt := @curr_cnt as dummy

from (

select actor_id,count(*) as cnt

from film_actor

group by actor_id

order by cnt desc

limit 10

) as der;

mysql 查詢效能優化

mysql 執行查詢,客戶端向 mysql 傳送請求的時候,mysql 伺服器執行一系列過程,保證查詢語句在 mysql 中得到最高效能的效率。客戶端傳送一條查詢給伺服器 2 伺服器先檢查查詢快取,如果命中了快取,則返回儲存在快取中的結果。否則,進入下乙個階段。3 伺服器進行 sql解析 預處理,再...

mysql查詢效能優化

mysql執行查詢的過程 如圖 1 客戶端首先通過客戶端 伺服器通訊協議與mysql伺服器建立起連線 2 客戶端傳送一條sql語句 判斷是否為查詢語句,如果是查詢語句,則先在查詢快取區雜湊查詢對應sql的資料,如果未找到,則需要呼叫解析器解析 預處理 再由優化器生成對應的查詢執行計畫 3 mysql...

MySql查詢效能優化

在訪問資料庫時,應該只請求需要的行和列。請求多餘的行和列會消耗mysql伺服器的cpu和記憶體資源,並增加網路開銷。例如在處理分頁時,應該使用limit限制mysql只返回一頁的資料,而不是向應用程式返回全部資料後,再由應用程式過濾不需要的行。當一行資料被多次使用時可以考慮將資料行快取起來,避免每次...