久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

MySQL 執(zhí)行計劃explain與索引數據結構推演過程是什么

144次閱讀
沒有評論

共計 15421 個字符,預計需要花費 39 分鐘才能閱讀完成。

自動寫代碼機器人,免費開通

了解 MySQL 執(zhí)行計劃 explain 與索引數據結構推演過程是什么?這個問題可能是我們日常學習或工作經常見到的。希望通過這個問題能讓你收獲頗深。下面是丸趣 TV 小編給大家?guī)淼膮⒖純热荩屛覀円黄饋砜纯窗桑?/p>

先建好數據庫表,演示用的 MySQL 表,建表語句:

CREATE TABLE `emp` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 主鍵 , `empno` int(11) DEFAULT NULL COMMENT 雇員工號 , `ename` varchar(255) DEFAULT NULL COMMENT 雇員姓名 , `job` varchar(255) DEFAULT NULL COMMENT 工作 , `mgr` varchar(255) DEFAULT NULL COMMENT 經理的工號 , `hiredate` date DEFAULT NULL COMMENT 雇用日期 , `sal` double DEFAULT NULL COMMENT 工資 , `comm` double DEFAULT NULL COMMENT 津貼 , `deptno` int(11) DEFAULT NULL COMMENT 所屬部門號 ,
 PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT= 雇員表 CREATE TABLE `dept` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 主鍵 , `deptno` int(11) DEFAULT NULL COMMENT 部門號 , `dname` varchar(255) DEFAULT NULL COMMENT 部門名稱 , `loc` varchar(255) DEFAULT NULL COMMENT 地址 ,
 PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT= 部門表 CREATE TABLE `salgrade` (`id` int(11) NOT NULL COMMENT 主鍵 , `grade` varchar(255) DEFAULT NULL COMMENT 等級 , `lowsal` varchar(255) DEFAULT NULL COMMENT 最低工資 , `hisal` varchar(255) DEFAULT NULL COMMENT 最高工資 ,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT= 工資等級表 CREATE TABLE `bonus` (`id` int(11) NOT NULL COMMENT 主鍵 , `ename` varchar(255) DEFAULT NULL COMMENT 雇員姓名 , `job` varchar(255) DEFAULT NULL COMMENT 工作 , `sal` double DEFAULT NULL COMMENT 工資 , `comm` double DEFAULT NULL COMMENT 津貼 ,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT= 獎金表 復制代碼

后續(xù)執(zhí)行計劃,查詢優(yōu)化,索引優(yōu)化等等知識的演練,基于以上幾個表來操作。

MySQL 執(zhí)行計劃

要進行 SQL 調優(yōu),你得知道要調優(yōu)的 SQL 語句是怎么執(zhí)行的,查看 SQL 語句的具體執(zhí)行過程,以加快 SQL 語句的執(zhí)行效率。

可以使用 explain + SQL 語句來模擬優(yōu)化器執(zhí)行 SQL 查詢語句,從而知道 MySQL 是如何處理 SQL 語句的。

關于 explain 可以看看官網介紹。

explain 的輸出格式

mysql explain select * from emp;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+| 1 | SIMPLE | emp | NULL | ALL | NULL | NULL | NULL | NULL | 1 | 100.00 | NULL |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+ 復制代碼

字段 id,select_type 等字段的解釋:

ColumnMeaningidThe SELECT identifier(該 SELECT 標識符)select_typeThe SELECT type(該 SELECT 類型)tableThe table for the output row(輸出該行的表名)partitionsThe matching partitions(匹配的分區(qū))typeThe join type(連接類型)possible_keysThe possible indexes to choose(可能的索引選擇)keyThe index actually chosen(實際選擇的索引)key_lenThe length of the chosen key(所選鍵的長度)refThe columns compared to the index(與索引比較的列)rowsEstimate of rows to be examined(檢查的預估行數)filteredPercentage of rows filtered by table condition(按表條件過濾的行百分比)extraAdditional information(附加信息)

id

select 查詢的序列號,包含一組數字,表示查詢中執(zhí)行 select 子句或者操作表的順序。

id 號分為三類:

如果 id 相同,那么執(zhí)行順序從上到下

mysql explain select * from emp e join dept d on e.deptno = d.deptno join salgrade sg on e.sal between sg.lowsal and sg.hisal;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+
| 1 | SIMPLE | e | NULL | ALL | NULL | NULL | NULL | NULL | 1 | 100.00 | NULL |
| 1 | SIMPLE | d | NULL | ALL | NULL | NULL | NULL | NULL | 1 | 100.00 | Using where; Using join buffer (Block Nested Loop) |
| 1 | SIMPLE | sg | NULL | ALL | NULL | NULL | NULL | NULL | 1 | 100.00 | Using where; Using join buffer (Block Nested Loop) |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+ 復制代碼

這個查詢,用 explain 執(zhí)行一下,id 序號都是 1,那么 MySQL 的執(zhí)行順序就是從上到下執(zhí)行的。

如果 id 不同,如果是子查詢,id 的序號會遞增,id 值越大優(yōu)先級越高,越先被執(zhí)行

mysql explain select * from emp e where e.deptno in (select d.deptno from dept d where d.dname = SALEDept 
+----+--------------+-------------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+--------------+-------------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+| 1 | SIMPLE | subquery2 | NULL | ALL | NULL | NULL | NULL | NULL | NULL | 100.00 | NULL |
| 1 | SIMPLE | e | NULL | ALL | NULL | NULL | NULL | NULL | 2 | 50.00 | Using where; Using join buffer (Block Nested Loop) |
| 2 | MATERIALIZED | d | NULL | ALL | NULL | NULL | NULL | NULL | 1 | 100.00 | Using where |
+----+--------------+-------------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+ 復制代碼

這個例子的執(zhí)行順序是先執(zhí)行 id 為 2 的,然后執(zhí)行 id 為 1 的。

id 相同和不同的,同時存在:相同的可以認為是一組,從上往下順序執(zhí)行,在所有組中,id 值越大,優(yōu)先級越高,越先執(zhí)行

還是上面那個例子,先執(zhí)行 id 為 2 的,然后按順序從上往下執(zhí)行 id 為 1 的。

select_type

主要用來分辨查詢的類型,是普通查詢還是聯(lián)合查詢還是子查詢。

select_type ValueJSON NameMeaningSIMPLENoneSimple SELECT (not using UNION or subqueries)PRIMARYNoneOutermost SELECTUNIONNoneSecond or later SELECT statement in a UNIONDEPENDENT UNIONdependent (true)Second or later SELECT statement in a UNION, dependent on outer queryUNION RESULTunion_resultResult of a UNION.SUBQUERYNoneFirst SELECT in subqueryDEPENDENT SUBQUERYdependent (true)First SELECT in subquery, dependent on outer queryDERIVEDNoneDerived tableMATERIALIZEDmaterialized_from_subqueryMaterialized subqueryUNCACHEABLE SUBQUERYcacheable (false)A subquery for which the result cannot be cached and must be re-evaluated for each row of the outer queryUNCACHEABLE UNIONcacheable (false)The second or later select in a UNION that belongs to an uncacheable subquery (see UNCACHEABLE SUBQUERY)SIMPLE 簡單的查詢,不包含子查詢和 union

mysql explain select * from emp;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+| 1 | SIMPLE | emp | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 100.00 | NULL |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+ 復制代碼

primary 查詢中若包含任何復雜的子查詢,最外層查詢則被標記為 Primaryunion 若第二個 select 出現在 union 之后,則被標記為 union

mysql explain select * from emp where deptno = 1001 union select * from emp where sal 5000;
+----+--------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+--------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+| 1 | PRIMARY | emp | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 25.00 | Using where |
| 2 | UNION | emp | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 33.33 | Using where |
| NULL | UNION RESULT | union1,2 | NULL | ALL | NULL | NULL | NULL | NULL | NULL | NULL | Using temporary |
+----+--------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+ 復制代碼

這條語句的 select_type 包含了 primary 和 union

dependent union 跟 union 類似,此處的 depentent 表示 union 或 union all 聯(lián)合而成的結果會受外部表影響 union result 從 union 表獲取結果的 selectdependent subquery subquery 的子查詢要受到外部表查詢的影響

mysql explain select * from emp e where e.empno in (select empno from emp where deptno = 1001 union select empno from emp where sal 5000);
+----+--------------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+--------------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+| 1 | PRIMARY | e | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 100.00 | Using where |
| 2 | DEPENDENT SUBQUERY | emp | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 25.00 | Using where |
| 3 | DEPENDENT UNION | emp | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 25.00 | Using where |
| NULL | UNION RESULT | union2,3 | NULL | ALL | NULL | NULL | NULL | NULL | NULL | NULL | Using temporary |
+----+--------------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+ 復制代碼

這條 SQL 執(zhí)行包含了 PRIMARY、DEPENDENT SUBQUERY、DEPENDENT UNION 和 UNION RESULT

subquery 在 select 或者 where 列表中包含子查詢

舉例:

mysql explain select * from emp where sal (select avg(sal) from emp) ;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+| 1 | PRIMARY | emp | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 33.33 | Using where |
| 2 | SUBQUERY | emp | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 100.00 | NULL |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+ 復制代碼

DERIVED from 子句中出現的子查詢,也叫做派生表 MATERIALIZED Materialized subquery?UNCACHEABLE SUBQUERY 表示使用子查詢的結果不能被緩存

例如:

mysql explain select * from emp where empno = (select empno from emp where deptno=@@sort_buffer_size);
+----+----------------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+----------------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+| 1 | PRIMARY | emp | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 100.00 | Using where |
| 2 | UNCACHEABLE SUBQUERY | emp | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 25.00 | Using where |
+----+----------------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+ 復制代碼

uncacheable union 表示 union 的查詢結果不能被緩存

table

對應行正在訪問哪一個表,表名或者別名,可能是臨時表或者 union 合并結果集。

如果是具體的表名,則表明從實際的物理表中獲取數據,當然也可以是表的別名表名是 derivedN 的形式,表示使用了 id 為 N 的查詢產生的衍生表當有 union result 的時候,表名是 union n1,n2 等的形式,n1,n2 表示參與 union 的 id

type

type 顯示的是訪問類型,訪問類型表示我是以何種方式去訪問我們的數據,最容易想到的是全表掃描,直接暴力的遍歷一張表去尋找需要的數據,效率非常低下。

訪問的類型有很多,效率從最好到最壞依次是:

system const eq_ref ref fulltext ref_or_null index_merge unique_subquery index_subquery range index ALL

一般情況下,得保證查詢至少達到 range 級別,最好能達到 ref

all 全表掃描,一般情況下出現這樣的 sql 語句而且數據量比較大的話那么就需要進行優(yōu)化

通常,可以通過添加索引來避免 ALL

index 全索引掃描這個比 all 的效率要好,主要有兩種情況:一種是當前的查詢時覆蓋索引,即我們需要的數據在索引中就可以索取一是使用了索引進行排序,這樣就避免數據的重排序 range 表示利用索引查詢的時候限制了范圍,在指定范圍內進行查詢,這樣避免了 index 的全索引掃描,適用的操作符:=, , , =, , =, IS NULL, BETWEEN, LIKE, or IN()

官網上舉例如下:

SELECT * FROM tbl_name
WHERE key_column = 10;

SELECT * FROM tbl_name
WHERE key_column BETWEEN 10 and 20;

SELECT * FROM tbl_name
WHERE key_column IN (10,20,30);

SELECT * FROM tbl_name
WHERE key_part1 = 10 AND key_part2 IN (10,20,30);

index_subquery 利用索引來關聯(lián)子查詢,不再掃描全表

value IN (SELECT key_column FROM single_table WHERE some_expr)

unique_subquery 該連接類型類似與 index_subquery,使用的是唯一索引

value IN (SELECT primary_key FROM single_table WHERE some_expr)

index_merge 在查詢過程中需要多個索引組合使用 ref_or_null 對于某個字段既需要關聯(lián)條件,也需要 null 值的情況下,查詢優(yōu)化器會選擇這種訪問方式

SELECT * FROM ref_table

WHERE key_column=expr OR key_column IS NULL;

fulltext 使用 FULLTEXT 索引執(zhí)行 joinref 使用了非唯一性索引進行數據的查找

SELECT * FROM ref_table WHERE key_column=expr;

SELECT * FROM ref_table,other_table
WHERE ref_table.key_column=other_table.column;

SELECT * FROM ref_table,other_table
WHERE ref_table.key_column_part1=other_table.column
AND ref_table.key_column_part2=1;

eq_ref 使用唯一性索引進行數據查找

SELECT * FROM ref_table,other_table
WHERE ref_table.key_column=other_table.column;

SELECT * FROM ref_table,other_table
WHERE ref_table.key_column_part1=other_table.column
AND ref_table.key_column_part2=1;

const 這個表至多有一個匹配行

SELECT * FROM tbl_name WHERE primary_key=1;

SELECT * FROM tbl_name
WHERE primary_key_part1=1 AND primary_key_part2=2;

例如:

mysql explain select * from emp where id = 1;
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+| 1 | SIMPLE | emp | NULL | const | PRIMARY | PRIMARY | 4 | const | 1 | 100.00 | NULL |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+ 復制代碼

system 表只有一行記錄(等于系統(tǒng)表),這是 const 類型的特例,平時不會出現

possible_keys

顯示可能應用在這張表中的索引,一個或多個,查詢涉及到的字段上若存在索引,則該索引將被列出,但不一定被查詢實際使用

MySQL 執(zhí)行計劃 explain 與索引數據結構推演過程是什么

key

實際使用的索引,如果為 null,則沒有使用索引,查詢中若使用了覆蓋索引,則該索引和查詢的 select 字段重疊

MySQL 執(zhí)行計劃 explain 與索引數據結構推演過程是什么

key_len

表示索引中使用的字節(jié)數,可以通過 key_len 計算查詢中使用的索引長度,在不損失精度的情況下長度越短越好

ref

顯示索引的哪一列被使用了,如果可能的話,是一個常數

rows

根據表的統(tǒng)計信息及索引使用情況,大致估算出找出所需記錄需要讀取的行數,此參數很重要,直接反應的 sql 找了多少數據,在完成目的的情況下越少越好

MySQL 執(zhí)行計劃 explain 與索引數據結構推演過程是什么

extra

包含額外的信息

using filesort 說明 mysql 無法利用索引進行排序,只能利用排序算法進行排序,會消耗額外的位置 using temporary 建立臨時表來保存中間結果,查詢完成之后把臨時表刪除 using index 這個表示當前的查詢是覆蓋索引的,直接從索引中讀取數據,而不用訪問數據表。如果同時出現 using where 表明索引被用來執(zhí)行索引鍵值的查找,如果沒有,表示索引被用來讀取數據,而不是真的查找 using where 使用 where 進行條件過濾 using join buffer 使用連接緩存 impossible where where 語句的結果總是 falseMySQL 索引基本知識

想要了解索引的優(yōu)化方式,必須要對索引的底層原理有所了解。

索引的優(yōu)點大大減少了服務器需要掃描的數據量幫助服務器避免排序和臨時表將隨機 io 變成順序 io(提升效率)索引的用處快速查找匹配 WHERE 子句的行從 consideration 中消除行, 如果可以在多個索引之間進行選擇,mysql 通常會使用找到最少行的索引如果表具有多列索引,則優(yōu)化器可以使用索引的任何最左前綴來查找行當有表連接的時候,從其他表檢索行數據查找特定索引列的 min 或 max 值如果排序或分組時在可用索引的最左前綴上完成的,則對表進行排序和分組在某些情況下,可以優(yōu)化查詢以檢索值而無需查詢數據行索引的分類

MySQL 執(zhí)行計劃 explain 與索引數據結構推演過程是什么

MySQL 索引數據結構推演

索引用于快速查找具有特定列值的行。

如果沒有索引,MySQL 必須從第一行開始,然后通讀整個表以找到相關的行。

表越大花費的時間越多,如果表中有相關列的索引,MySQL 可以快速確定要在數據文件中間查找的位置,而不必查看所有數據。這比順序讀取每一行要快得多。

既然 MySQL 索引能幫助我們快速查詢到數據,那么它的底層是怎么存儲數據的呢?

幾種可能的存儲結構

hash

hash 表的索引格式

MySQL 執(zhí)行計劃 explain 與索引數據結構推演過程是什么

hash 表存儲數據的缺點:

利用 hash 存儲的話需要將所有的數據文件添加到內存,比較耗費內存空間如果所有的查詢都是等值查詢,那么 hash 確實很快,但是在實際工作環(huán)境中范圍查找的數據更多一些,而不是等值查詢,這種情況下 hash 就不太適合了

事實上,MySQL 存儲引擎是 memory 時,索引數據結構采用的就是 hash 表。

二叉樹

二叉樹的結構是這樣的:

MySQL 執(zhí)行計劃 explain 與索引數據結構推演過程是什么

二叉樹會因為樹的深度而造成數據傾斜,如果樹的深度過深,會造成 io 次數變多,影響數據讀取的效率。

AVL 樹 需要旋轉,看圖例:

MySQL 執(zhí)行計劃 explain 與索引數據結構推演過程是什么

紅黑樹 除了旋轉操作還多了一個變色的功能(為了減少旋轉),這樣雖然插入的速度快,但是損失了查詢的效率。

MySQL 執(zhí)行計劃 explain 與索引數據結構推演過程是什么

二叉樹、AVL 樹、紅黑樹 都會因為樹的深度過深而造成 io 次數變多,影響數據讀取的效率。

再來看一下 B 樹

B 樹特點:

所有鍵值分布在整顆樹中搜索有可能在非葉子結點結束,在關鍵字全集內做一次查找, 性能逼近二分查找每個節(jié)點最多擁有 m 個子樹根節(jié)點至少有 2 個子樹分支節(jié)點至少擁有 m / 2 顆子樹(除根節(jié)點和葉子節(jié)點外都是分支節(jié)點)所有葉子節(jié)點都在同一層、每個節(jié)點最多可以有 m - 1 個 key,并且以升序排列

MySQL 執(zhí)行計劃 explain 與索引數據結構推演過程是什么

圖例說明:

每個節(jié)點占用一個磁盤塊,一個節(jié)點上有兩個升序排序的關鍵字和三個指向子樹根節(jié)點的指針,指針存儲的是子節(jié)點所在磁盤塊的地址。

兩個關鍵詞劃分成的三個范圍域對應三個指針指向的子樹的數據的范圍域。

以根節(jié)點為例,關鍵字為 16 和 34,P1 指針指向的子樹的數據范圍為小于 16,P2 指針指向的子樹的數據范圍為 16~34,P3 指針指向的子樹的數據范圍為大于 34。

查找關鍵字過程:

1、根據根節(jié)點找到磁盤塊 1,讀入內存。【磁盤 I/O 操作第 1 次】

2、比較關鍵字 28 在區(qū)間(16,34),找到磁盤塊 1 的指針 P2。

3、根據 P2 指針找到磁盤塊 3,讀入內存。【磁盤 I/O 操作第 2 次】

4、比較關鍵字 28 在區(qū)間(25,31),找到磁盤塊 3 的指針 P2。

5、根據 P2 指針找到磁盤塊 8,讀入內存。【磁盤 I/O 操作第 3 次】

6、在磁盤塊 8 中的關鍵字列表中找到關鍵字 28。

由此,我們可以得知 B 樹存儲的缺點:

每個節(jié)點都有 key,同時也包含 data,而每個頁存儲空間是有限的,如果 data 比較大的話會導致每個節(jié)點存儲的 key 數量變小當存儲的數據量很大的時候會導致深度較大,增大查詢時磁盤 io 次數,進而影響查詢性能那么 MySQL 索引數據結構是什么呢

官網:Most MySQL indexes (PRIMARY KEY, UNIQUE, INDEX, and FULLTEXT) are stored in B-trees

不要誤會,其實 MySQL 索引的存儲結構是 B + 樹,上面我們一頓分析,知道 B 樹是不合適的。

mysql 索引數據結構 —B+Tree

B+Tree 是在 BTree 的基礎之上做的一種優(yōu)化,變化如下:

1、B+Tree 每個節(jié)點可以包含更多的節(jié)點,這個做的原因有兩個,第一個原因是為了降低樹的高度,第二個原因是將數據范圍變?yōu)槎鄠€區(qū)間,區(qū)間越多,數據檢索越快。

2、非葉子節(jié)點存儲 key,葉子節(jié)點存儲 key 和數據。

3、葉子節(jié)點兩兩指針相互連接(符合磁盤的預讀特性),順序查詢性能更高。

B+ 樹存儲查找示意圖:

MySQL 執(zhí)行計劃 explain 與索引數據結構推演過程是什么

注意:

在 B +Tree 上有兩個頭指針,一個指向根節(jié)點,另一個指向關鍵字最小的葉子節(jié)點,而且所有葉子節(jié)點(即數據節(jié)點)之間是一種鏈式環(huán)結構。

因此可以對 B+Tree 進行兩種查找運算:一種是對于主鍵的范圍查找和分頁查找,另一種是從根節(jié)點開始,進行隨機查找。

由于 B + 樹葉子結點只存放 data,根節(jié)點只存放 key,那么我們計算一下,即使只有 3 層 B + 樹,也能制成千萬級別的數據。

你得知道的技(zhuang)術(b)名詞

假設有這樣一個表如下,其中 id 是主鍵:

mysql select * from stu;
+------+---------+------+| id | name | age |
+------+---------+------+| 1 | Jack Ma | 18 |
| 2 | Pony | 19 |
+------+---------+------+ 復制代碼

回表

我們對普通列建普通索引,這時候我們來查:

select * from stu where name= Pony 復制代碼

由于 name 建了索引,查詢時先找 name 的 B + 樹,找到主鍵 id 后,再找主鍵 id 的 B + 樹,從而找到整行記錄。

這個最終會回到主鍵上來查找 B + 樹,這個就是回表。

覆蓋索引

如果是這個查詢:

mysql select id from stu where name= Pony 復制代碼

就沒有回表了,因為直接找到主鍵 id,返回就完了,不需要再找其他的了。

沒有回表就叫覆蓋索引。

最左匹配

再來以 name 和 age 兩個字段建組合索引(name, age),然后有這樣一個查詢:

select * from stu where name=? and age=? 復制代碼

這時按照組合索引 (name, age) 查詢,先匹配 name,再匹配 age,如果查詢變成這樣:

select * from stu where age=? 復制代碼

直接不按 name 查了,此時索引不會生效,也就是不會按照索引查詢 — 這就是最左匹配原則。

加入我就要按 age 查,還要有索引來優(yōu)化呢?可以這樣做:

(推薦)把組合索引 (name, age) 換個順序,建 (age, name) 索引或者直接把 age 字段單獨建個索引索引下推

可能也叫謂詞下推。。。

select t1.name,t2.name from t1 join t2 on t1.id=t2.id 復制代碼

t1 有 10 條記錄,t2 有 20 條記錄。

我們猜想一下,這個要么按這個方式執(zhí)行:

先 t1,t2 按 id 合并(合并后 20 條),然后再查 t1.name,t2.name

或者:

先把 t1.name,t2.name 找出來,再按照 id 關聯(lián)

如果不使用索引條件下推優(yōu)化的話,MySQL 只能根據索引查詢出 t1,t2 合并后的所有行,然后再依次比較是否符合全部條件。

當使用了索引條件下推優(yōu)化技術后,可以通過索引中存儲的數據判斷當前索引對應的數據是否符合條件,只有符合條件的數據才將整行數據查詢出來。

小結 Explain 為了知道優(yōu)化 SQL 語句的執(zhí)行,需要查看 SQL 語句的具體執(zhí)行過程,以加快 SQL 語句的執(zhí)行效率。索引優(yōu)點及用處。索引采用的數據結構是 B + 樹。回表,覆蓋索引,最左匹配和索引下推。

感謝各位的閱讀!看完上述內容,你們對 MySQL 執(zhí)行計劃 explain 與索引數據結構推演過程是什么大概了解了嗎?希望文章內容對大家有所幫助。如果想了解更多相關文章內容,歡迎關注丸趣 TV 行業(yè)資訊頻道。

向 AI 問一下細節(jié)

丸趣 TV 網 – 提供最優(yōu)質的資源集合!

正文完
 
丸趣
版權聲明:本站原創(chuàng)文章,由 丸趣 2023-12-18發(fā)表,共計15421字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發(fā)布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 石楼县| 合山市| 商河县| 嘉善县| 高雄市| 河曲县| 苏尼特右旗| 游戏| 包头市| 禄劝| 嘉黎县| 措勤县| 红安县| 济宁市| 延津县| 山东省| 裕民县| 崇州市| 大同市| 韶山市| 镇原县| 右玉县| 信宜市| 吐鲁番市| 滨州市| 丹巴县| 化德县| 浙江省| 南丰县| 崇州市| 盐边县| 郧西县| 鹰潭市| 兴国县| 磐安县| 永年县| 延安市| 禹州市| 阿鲁科尔沁旗| 义马市| 金塔县|