一、MySQL如何進行SQL調優?
我的回答:
面試官好!我想從SQL語句本身和數據庫結構兩方面來做MySQL的SQL調優。
????????首先會優化SQL寫法,比如避免用SELECT *、減少子查詢嵌套,用JOIN代替,還有合理使用索引,比如給查詢頻繁的字段建索引,同時避免索引失效的情況,像用函數操作索引列。
????????另外,會關注表結構設計,比如拆分大表、使用合適的數據類型。還會通過慢查詢日志定位低效SQL,用EXPLAIN分析執行計劃。我在學習中試過給查詢頻繁的字段加索引,查詢效率確實提升了不少,這讓我覺得調優能直接解決實際問題,所以也在持續積累這方面的經驗,希望能更好地保證數據庫性能。
回答重點官方答案:
平時進行調優,主要是觀察慢SQL,然后利用explain分析查詢語句的執行計劃來優化查詢語句。
1.合理設計索引,利用聯合索引進行覆蓋索引的優化,避免回表的發生,減少一次查詢和隨機I/0。
2. 避免使用select *,只查詢必要的字段
3.避免在SQL中進行函數計算等操作,使得無法命中索引。
4.避免使用前綴帶 % 的模糊查詢,導致全表掃描
5.注意聯合索引需要滿足最左匹配規則
6.不要對無索引字段進行排序操作
7.連表查詢還要注意不同字段的字符集是否一致,否則也會導致全表掃描。
除此之外,還可以利用緩存來優化,一些變化少或者訪問頻繁的數據設置到緩存中,可以減輕數據庫的壓力,提升查詢效率,還可以通過業務來優化,例如少展示一些不必要的字段,減少多表查詢情況,將列表查詢替換成分頁分批查詢等等。
若接著問explain執行計劃中的各個字段
重點關注下面字段
二、如何使用MySQL的explain語句進行查詢分析?
我的答案:
首先就是要在需要分析的SQL前加上explain,執行后會得到一張表,里面的字段能反映查詢的關鍵信息,比如
看type字段,它表示連接類型,像const,eq_ref是比較好的。如果出現all就是全表掃描,就需要優化。
possible key字段是可能用到的索引。
key字段能看出實際用到的索引,如果是null就說明沒走索引,此時要檢查索引設計或SQL寫法。
key_len是索引中使用的字節數,是索引字段最大可能長度,長度越短越好
rows字段大概估計要掃描的行數,數值越小越好。
我之前聯系的時候,寫了一個沒有加索引的sql,用explain發現type是all,rows很大,加了索引之后,type變成ref,rows小了很多。查詢速度快了很多。現在我每次寫復雜sql都會先用explain分析一下,看是否有全表掃描、索引失效的情況,再針對性優化,慢慢的也更能理解索引和查詢執行的關系了,以后會繼續用這個工具提升SLQ效率
回答重點官方答案:
explain 主要用來 SQL 分析,它主要的屬性詳解如下:
- id :查詢的執行順序的標識符,值越大優先級越高。簡單查詢的 id 通常為 1,復雜查詢(如包含子查詢或 UNION)的 id 會有多個。
- select_type(重要):查詢的類型,如 SIMPLE(簡單查詢)、PRIMARY(主查詢)、SUBQUERY(子查詢)等。
- table :查詢的數據表。
- type(重要):訪問類型,如 ALL(全表掃描)、index(索引掃描)、range(范圍掃描)等。一般來說,性能從好到差的順序是:const > eq_ref > ref > range > index > ALL。
- possible_keys :可能用到的索引。
- key(重要):實際用到的索引。
- key_len :用到索引的長度。
- ref :顯示索引的哪一列被使用。
- rows(重要):估計要掃描的行數,值越小越好。
- filtered :顯示查詢條件過濾掉的行的百分比。一個高百分比表示查詢條件的選擇性好。
- Extra(重要):額外信息,如 Using index(表示使用覆蓋索引)、Using where(表示使用 WHERE 條件進行過濾)、Using temporary(表示使用臨時表)、Using filesort(表示需要額外的排序步驟)。
type 詳解:
- system:表示查詢的表只有一行(系統表)。這是一個特殊的情況,不常見。
- const:表示查詢的表最多只有一行匹配結果。這通常發生在查詢條件是主鍵或唯一索引,并且是常量比較。
- eq_ref:表示對于每個來自前一張表的行,MySQL 僅訪問一次這個表。這通常發生在連接查詢中使用主鍵或唯一索引的情況下。
- ref:MySQL 使用非唯一索引掃描來查找行。查詢條件使用的索引是非唯一的(如普通索引)。
- range:表示 MySQL 會掃描表的一部分,而不是全部行。范圍掃描通常出現在使用索引的范圍查詢中(如 BETWEEN、>,<,>=,<= )。
- index:表示 MySQL 掃描索引中的所有行,而不是表中的所有行。即使索引列的值覆蓋查詢,也需要掃描整個索引。
- all(性能最差):表示 MySQL 需要掃描表中的所有行,即全表掃描。通常出現在沒有索引的查詢條件中。
三、MySQL中的索引數量是否越多越好,為什么?
我的回答:
索引并不是越多越好,因為索引不論是從時間上還是空間上都是有一定成本的。
索引雖然能夠加快查詢速度,但會增加寫操作(插入、更新、刪除)的開銷,每次增刪改數據,不僅僅要修改表中數據,還要維護對應索引結構,索引越多,維護成本越高,可能拖慢寫入性能。而且索引會占用額外的存儲空間,太多的索引會浪費磁盤空間
另外查詢時數據庫可能會在多個索引中選擇不合適的,反而影響查詢效率。我之前試過給一張表加了多個索引,結果插入數據的速度明顯慢了許多,所以索引要按需創建,要在查詢和寫入之間找平衡,所以我現在會根據實際查詢場景合理建索引,避免盲目添加。
回答重點(官方答案)
索引并不是越多越好。因為索引不論從時間還是空間上都是有一定成本的
從時間上
每次對表中的數據進行增刪改 (INSERT、UPDATE 或 DELETE) 的時候,索引也必須被更新,這會增加寫入操作的開銷。例如刪除了一個 name 為張三的記錄,不僅主鍵索引上需要修改,如果 name 字段有索引,那么 name 索引也需要修改,所以索引越多需要修改的地方也就越多,時間開銷就大了,并且 B+ 樹可能會有頁分裂、合并等操作,時間開銷就會更大。
還有一點需要注意:MySQL 有個查詢優化器,它需要分析當前的查詢,選擇最優的計劃,這過程就需要考慮選擇哪個索引的查詢成本低。如果索引過多,那么會導致優化器耗費更多的時間在選擇上,甚至可能因為數據的不準確而選擇了次優的索引。從空間上
每建立一個二級索引,都需要新建一個 B+ 樹,默認每個數據頁都是 16KB,如果數據量很大,索引又很多,占用的空間可不小。