本文咱們來談談項目中經常使用的 20 條 MySQL 優化方法,效率至少提升 3倍!前端
具體以下:面試
使⽤ EXPLAIN 判斷 SQL 語句是否合理使用索引,儘可能避免 extra 列出現:Using File Sort、Using Temporary 等。sql
重要SQL必須被索引:update、delete 的 where 條件列、order by、group by、distinct 字段、多表 join 字段。數據庫
對於聯合索引來講,若是存在範圍查詢,好比between、>、<等條件時,會形成後面的索引字段失效。數組
對於聯合索引來講,要遵照最左前綴法則:舉列來講索引含有字段 id、name、school
,能夠直接用 id 字段,也能夠 id、name 這樣的順序,可是 name; school 都沒法使用這個索引。因此在建立聯合索引的時候必定要注意索引字段順序,經常使用的查詢字段放在最前面。網絡
必要時可使用 force index
來強制查詢走某個索引: 有的時候MySQL優化器採起它認爲合適的索引來檢索 SQL 語句,可是可能它所採用的索引並非咱們想要的。這時就能夠採用 forceindex 來強制優化器使用咱們制定的索引。架構
對於非標準的日期字段,例如字符串的日期字段,進行分區裁剪查詢時會致使沒法識辨,依舊走全表掃描。併發
儘可能使用 TIMESTAMEP 類型,由於其存儲空間只須要 datetime 的一半。函數
SELECT 只獲取必要的字段,禁止使用 SELECT *。這樣能減小沒必要要的消耗(CPU、IO、內存、網絡帶寬),增長使用覆蓋索引的可能性;當表結構發生改變時,表結構變動對前端程序基本無影響。高併發
SQL 中避免出現 now()
、rand()
、sysdate()
、current_user()
等不肯定結果的函數。在語句級複製場景下,引發主從數據不一致;不肯定值的函數,產生的 SQL 語句沒法使用 QUERY CACHE。
避免在 where 子句中對字段進行 null 值
判斷:對於 null 的判斷會致使引擎放棄使用索引而進行全表掃描。
避免在where子句中對字段進行表達式操做:由於對字段就好了算術運算,這會形成引擎放棄使用索引。
禁止使用 % 前導查詢,例如:like 「%abc」,⽆法利⽤到索引。
在平常中你會發現全模糊匹配的查詢,因爲 MySQL 的索引是 B+ 樹結構,因此當查詢條件爲全模糊時,例如 %AB%
、%AB
,索引沒法使用,這時須要經過添加其餘選擇度高的列或者條件做爲一種補充,從而加快查詢速度。僅AB%
形式的能夠避免通配符引發索引屏蔽。
OR 兩邊的字段中,若是有一個不是索引字段,而其它條件也不是索引字段,會形成該查詢不走索引的狀況。不少時候都會使用 IN 進行替代,或者使用 union all 或者是 union(必要的時候)的方式來代替「or」也會獲得更好的效果。但 SQL 語句中 IN 包含的值不宜過多,應少於 1000 個。過多會使隨機 IO 增大,影響性能。
使用 IN 是由於 MySQL 對其作了相應的優化,即將 IN 中的常量所有存儲在一個數組裏面,並且這個數組是排好序的。可是若是數值較多,產生的消耗比較大。
再例如:
select id from t where num in(1,2,3)
對於連續的數值,能用 between 就不要用 in 了;再或者使用鏈接來替換。
禁止使⽤負向查詢,例如:not in、!=、<>、not like。
在對字符串類型的索引進行大於運算時,會致使全表掃描。因此應改成區間between區間範圍運算。
另外 order by/group by
的 SQL 涉及排序,儘可能在索引中包含排序字段,並讓排序字段的排序順序與索引列中的順序相同,這樣能夠避免排序或減小排序次數。若是排序字段沒有用到索引,就儘可能少排序。
order by rand() 會爲表增長几個僞列,而後用 rand() 函數爲每一行數據計算 rand() 值,最後基於該行排序,這一般都會生成磁盤上的臨時表,所以效率很是低。建議先使用 rand() 函數得到隨機的主鍵值,而後經過主鍵獲取數據。
union 和 union all 的差別主要是前者須要將結果集合並後再進行惟一性過濾操做,這就會涉及到排序,增長大量的CPU運算,加大資源消耗及延遲。固然,union all 的前提條件是兩個結果集沒有重複數據。
儘可能採用批量 SQL 語句,減小與數據庫交互次數。
獲取⼤量數據時,建議分批次獲取數據,每次獲取數據少於 5000 條,結果集應⼩於 1M。
不要用一個SQL解決全部事情,能夠分步驟作,省時、易理解、優化。且 MySQL 也十分擅長處理短而簡單的 SQL,整體耗時會更短,並且也不會產生臃腫的 SQL,讓人難以理解和優化。
拆分複雜 SQL 爲多個 小SQL,避免⼤事務。簡單的 SQL 容易使用到 MySQL 的 QUERY CACHE;減小鎖表時間特別是 MyISAM;可使用多核 CPU。
delete from table_name;
會產生大量 undo 和 redo 日誌,執行時間很長,可採用 TRUNCATE TABLE tablename;
col_utf8mb4 = col_utf8
關聯類型都是 varchar ,但字符集不一樣,沒法使用索引。使用過程當中要特別注意。
這也是一個被面試中常常會問到的問題,對於下面的四條 SELECT 語句:
select count(*) from table … ; select count(1) from table … ; select count(primary key) from table … ; select count(index key) from table …;
哪一條的執行效率最高呢?這個問題須要具體問題具體分析,不能一律而論。這裏舉 SELECT count(1) 這條 SQL 爲例。
優化前和優化後,執行效率相差2倍。就添加了一個索引。
優化思路 : 是選擇索引 key_len
最短的二級索引效率高,不要使用全表掃描(PK 聚族索引會全表掃描),由於索引 key_len
越短,讀取頁面越少,進而 IO_COST
越小。
prepared statement
和綁定變量,能夠提高性能並避免 SQL 注入重點總結一下:SQL 的執行過程->查詢優化器的工做原理->SQL 執行計劃的解讀->MySQL 慢查詢日誌和分析->SQL 經常使用的優化手段->SQL 編寫規範->深刻實際業務對數據庫訪問進行優化。