當面試官問你mysql優化
首先要知道mysql
分爲兩個層次。你要逐一從各個層次講解mysql優化,讓面試官知道,哇,原來你對mysql這麼瞭解。
面試官:你知道哪些mysql優化?
我: …巴拉巴拉巴拉。
mysql結構層次
首先,mysql分爲server層和引擎層。
server層有連接器
。對於連接器可以通過建立連接池來進行優化。連接器進行連接的時候會消耗資源,還會進行權限驗證等操作,爲了避免頻繁創建連接,所以使用連接池。
server層還有緩存模塊
,只不過緩存模塊
在新版本,也就是mysql8中被去掉了。
server層還有分析器
,進行語法分析之類的,這裏沒啥可優化的。
server層還有優化器
,優化器會對sql語句進行優化,以及選擇索引等操作。針對這裏的優化就是寫出更好的sql語句,儘量減少優化器的工作,用對索引,創建更好的索引等。具體的後面在詳細說明。
server層還有執行器
,負責執行優化器輸出的執行計劃,執行計劃可以通過explain
語句來查看,通過執行計劃可以看到執行掃描的行數,是否使用索引,在連表時候使用的算法,是否用到了排序等等信息。
除了server層就是引擎層的優化。引擎層的優化主要是通過優化sql語句和創建索引來完成。重點也就是sql語句和索引部分。
sql語句的優化
select * 還是字段問題
很多人都會說要使用select 字段
而不是select *
,那麼這到底爲什麼呢?真的慢嗎?慢在哪裏?
select * 的問題,拿innoDB引擎來說,其實innoDB中,不管是select * 還是字段,他的速度都差不多,因爲所有的數據都存放在主鍵索引
中,主鍵索引是一個聚簇索引
,主鍵id和數據放在一起,所以它拿的時候,都可以拿到所有字段。但是還是推薦需要哪個去哪個字段,這是因爲雖然都可以拿到,但是拿的東西許多,要傳輸的數據也就越多,而這會造成更大的網絡開銷,耗費網絡io資源,如果你的網絡不在乎這些,那麼其實速度上差不多。
count (*)問題
count語句用於求數量,這個在後臺中用的尤其多。關於這個問題,到底是count()好還是count(id)好呢?有的人覺得id更好,因爲走了主鍵索引。其實不是,更好的是count(*)
。因爲mysql團隊對count()這個語句進行了優化。具體怎麼優化的,因爲篇幅關係還請參考我的另一篇文章。所以千萬不要在寫什麼count(id)了,請直接使用count(*)吧。
不過這個主要是innoDB引擎,因爲Myisam引擎的總數量是有記錄的,所以不需要全表掃描,這也是兩個引擎的不同處。不過Myisam引擎在進行where條件的count時候還是需要全表掃描的。
innoDB引擎count的執行原理如果感興趣可以參考我這個文章。
join連表問題
很多時候都要進行join連表操作,有的人覺得連表很慢,還不如自己查詢兩次來的快。其實並不是,如果滿足以下幾點,那麼連表的速度是最優的:
-
小表驅動大表,也就是數據量小的表作爲主表進行連接
-
連表條件增加索引
這樣的話其實連表是最快的,主要是因爲連表條件會走索引。
如果連表條件沒有索引,那麼抱歉,速度真的很慢,他會對兩個表全都全表掃描。。。
mysql innoDB join的執行原理,有興趣的可以參考我這個文章。
查詢單條記錄問題
如果你只需要查詢一條記錄,那麼加上limit 1
會更快。這是爲什麼呢?因爲innoDB再查詢到你需要的數據後會繼續往後查詢,直到查詢到不滿足條件爲止,所以如果你這麼寫:
select * from sys where user = 1;
如果user有索引,那麼會從索引上找到user = 1的記錄,然後從索引這個位置接着往下找,找到user = 2發現不滿足條件,然後回表查詢,返回數據。但是你要是加上limit 1
select * from sys where user = 1 limit 1;
這時候找到user = 1的記錄就不會再往下找了,所以速度會更快。
不過唯一索引
沒有這個問題,因爲唯一索引是唯一的。
覆蓋索引問題
使用覆蓋索引可以避免innoDB引擎回表查詢,這樣速度也會提升,什麼是回表呢?就是當從其他索引上查詢到數據後,其他索引上只能查到主鍵id,還需要再走一遍主鍵索引,從主鍵索引上取數據。如果你的普通索引上通過建立聯合索引,來把數據放進去,就不需要回表了。
order by排序字段建立索引
給排序字段建立索引是因爲索引是有序的,不需要排序,這樣的話排序時候直接走有序索引就避免了排序過程。不然mysql還要進行以下排序。這樣就可以把排序的時間省掉。
order by 的具體執行原理可以參考我下面的文章:
where 字段建立索引
對於常用的where字段可以建立索引,多個where字段可以建立聯合索引。對於不怎麼常用的查詢,我們就沒必要建立索引了,畢竟索引建多了並不好,維護索引也是有代價的。
慢查詢日誌
一定要打開慢查詢日誌,如果發現慢查詢需要進行sql優化了。
避免長事務
不要寫長事務,不要把不必要的查詢操作納入事務中。
mysql函數問題
不要再查詢中使用mysql的函數,因爲使用函數會導致不走索引。
mysql類型轉換問題
不要再查詢中讓mysql進行類型轉換,比如
select * from user where mobile = 123.........
因爲mysql進行類型轉換會使用到函數,而用到函數會導致不走索引。
多看執行計劃
通過explain查詢執行計劃,看有沒有用到索引,mysql有時候會選錯索引,因爲是否走索引是通過抽樣調查來決定的,所以並不準確,再加上要回表查詢。所以有時候會不走索引。