邏輯分層
下面是MySQL的邏輯分層圖:
連接層:連接與線程處理,這一層並不是MySQL獨有,一般的基於C/S架構的都有類似組件,比如連接處理、授權認證、安全等。
服務層:包括緩存查詢、解析器、優化器,這一部分是MySQL核心功能,包括解析、優化SQL語句,查詢緩存目錄,內置函數(日期、時間、加密等函數)的實現。
引擎層:負責數據存儲,存儲引擎的不同,存儲方式、數據格式、提取方式等都不相同,這一部分也是很大影響數據存儲與提取的性能的;對存儲層的抽象。
存儲層:存儲數據,文件系統。
存儲引擎
查看數據庫支持的存儲引擎:show engines;
如果要想查看數據庫默認使用哪個引擎,可以通過使用命令: show variables like '%storage_engine%';
InnoDB,MyISAM的主要區別:
InnoDB:在MySQL5.5開始作為默認的存儲引擎,支持事務,行級鎖,適合高並發場景,XA協議支持分布式事務,事務優先。
MyISAM:不支持事務,性能優先,表級鎖,不適合高並發場景。
sql執行順序:https://www.cnblogs.com/annsshadow/p/5037667.html
explain-執行計划
explain顯示了mysql如何使用索引來處理select語句以及連接表。可以幫助選擇更好的索引和寫出更優化的查詢語句。
使用方法,在select語句前加上explain就可以了:
如:explain select surname,first_name form a,b where a.id=b.id
EXPLAIN列的解釋:
id:情況有三種,分別是:id相同表示加載表的順序是從上到下。id不同id值越大,優先級越高,越先被執行。id有相同,也有不同,同時存在。id相同的可以認為是一組,從上往下順序執行;在所有的組中,id的值越大,優先級越高,越先執行。
table:顯示這一行的數據是關於哪張表的
type:這是重要的列,顯示連接使用了何種類型。
possible_keys:顯示可能應用在這張表中的索引。但是並不表示此索引會真正地被 MySQL 使用到,如果為空,沒有可能的索引。
key: 實際使用的索引。如果為NULL,則沒有使用索引。很少的情況下,MYSQL會選擇優化不足的索引。這種情況下,可以在SELECT語句中使用USE INDEX(indexname)來強制使用一個索引或者用IGNORE INDEX(indexname)來強制MYSQL忽略索引
key_len:使用的索引的長度。在不損失精確性的情況下,長度越短越好
ref:顯示索引的哪一列被使用了,如果可能的話,是一個常數
rows:MySQL 查詢優化器根據統計信息, 估算 SQL 要查找到結果集需要掃描讀取的數據行數.這個值非常直觀顯示 SQL 的效率好壞, 原則上 rows 越少越好.
Extra:關於MYSQL如何解析查詢的額外信息
select_type
select_type
表示了查詢的類型, 它的常用取值有:
-
SIMPLE, 表示此查詢不包含 UNION 查詢或子查詢
-
PRIMARY, 表示此查詢是最外層的查詢
-
UNION, 表示此查詢是 UNION 的第二或隨后的查詢
-
DEPENDENT UNION, UNION 中的第二個或后面的查詢語句, 取決於外面的查詢
-
UNION RESULT, UNION 的結果
-
SUBQUERY, 子查詢中的第一個 SELECT
-
DEPENDENT SUBQUERY: 子查詢中的第一個 SELECT, 取決於外面的查詢. 即子查詢依賴於外層查詢的結果.
最常見的查詢類別應該是 SIMPLE
了, 比如當我們的查詢沒有子查詢, 也沒有 UNION 查詢時, 那么通常就是 SIMPLE
類型
type
type
字段比較重要, 它提供了判斷查詢是否高效的重要依據依據. 通過 type
字段, 我們判斷此次查詢是 全表掃描
還是 索引掃描
等,(常見的)從最好到最差的連接類型為const、eq_reg、ref、range、index和ALL
一般來說,得保證查詢至少達到range級別,最好能達到ref。
-
system
: 表中只有一條數據. 這個類型是特殊的const
類型. -
const
: 針對主鍵或唯一索引的等值查詢掃描, 最多只返回一行數據. const 查詢速度非常快, 因為它僅僅讀取一次即可 eq_ref
: 此類型通常出現在多表的 join 查詢, 表示對於前表的每一個結果, 都只能匹配到后表的一行結果. 並且查詢的比較操作通常是=
, 查詢效率較高.ref
: 此類型通常出現在多表的 join 查詢, 針對於非唯一或非主鍵索引, 或者是使用了最左前綴(索引使用順序和定義順序一致)
規則索引的查詢.range
: 表示使用索引范圍查詢, 通過索引字段范圍獲取表中部分數據記錄. 這個類型通常出現在 =, <>, >, >=, <, <=, IS NULL, <=>, BETWEEN, IN() 操作中.
當type
是range
時, 那么 EXPLAIN 輸出的ref
字段為 NULL, 並且key_len
字段是此次查詢中使用到的索引的最長的那個.(in查詢時有時候會失效,從而變成無索引All)index
: 表示全索引掃描(full index scan), 和 ALL 類型類似, 只不過 ALL 類型是全表掃描, 而 index 類型則僅僅掃描所有的索引, 而不掃描數據.index
類型通常出現在: 所要查詢的數據直接在索引樹中就可以獲取到, 而不需要掃描數據. 當是這種情況時, Extra 字段 會顯示Using index
.- ALL: 表示全表掃描, 這個類型的查詢是性能最差的查詢之一. 通常來說, 我們的查詢不應該出現 ALL 類型的查詢, 因為這樣的查詢在數據量大的情況下, 對數據庫的性能是巨大的災難. 如一個查詢是 ALL 類型查詢, 那么一般來說可以對相應的字段添加索引來避免.
ALL
類型因為是全表掃描, 因此在相同的查詢條件下, 它是速度最慢的.而 index
類型的查詢雖然不是全表掃描, 但是它掃描了所有的索引, 因此比 ALL 類型的稍快.
Extra
EXplain 中的很多額外的信息會在 Extra 字段顯示, 常見的有以下幾種內容:
-
Using filesort
當 Extra 中有Using filesort
時, 表示 MySQL 需額外的排序操作, 不能通過索引順序達到排序效果. 一般有Using filesort
, 都建議優化去掉, 因為這樣的查詢 CPU 資源消耗大.
SELECT * FROM order_info ORDER BY product_name;(索引是:`user_product_detail_index` (`user_id`, `product_name`, `productor`)
)
product_name
來排序, 因此不能使用索引進行優化, 進而會產生 Using filesort
.如果我們將排序依據改為
ORDER BY user_id, product_name
, 那么就不會出現 Using filesort
了
- Using index "覆蓋索引掃描", 表示查詢在索引樹中就可查找所需數據, 不用掃描表數據文件, 往往說明性能不錯
- Using temporary 查詢有使用臨時表, 一般出現於排序, 分組和多表 join 的情況, 查詢效率不高, 建議優化.
優化小結:
-
最左前綴(索引使用順序和定義順序一致)
- 將含有in的范圍查詢放到where條件的最后,防止索引失效
- using where 需要回原表查詢,using index不需要回原表查詢