日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

mysql explain实践

發(fā)布時(shí)間:2024/4/13 数据库 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql explain实践 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前言

使用EXPLAIN關(guān)鍵字可以模擬優(yōu)化器執(zhí)行SQL語句,從而知道MySQL是如何處理SQL語句的。幫助分析查詢語句或是結(jié)構(gòu)的性能瓶頸。
在 select 語句之前增加 explain 關(guān)鍵字,MySQL 會(huì)在查詢上設(shè)置一個(gè)標(biāo)記,執(zhí)行查詢時(shí),會(huì)返回執(zhí)行計(jì)劃的信息,而不是執(zhí)行這條SQL(如果 from 中包含子查詢,仍會(huì)執(zhí)行該子查詢,將結(jié)果放 入臨時(shí)表中)。

數(shù)據(jù)準(zhǔn)備

DROP TABLE IF EXISTS `actor`; CREATE TABLE `actor` (`id` int(11) NOT NULL, `name` varchar(45) DEFAULT NULL, `update_time` datetime DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;INSERT INTO `actor` (`id`, `name`, `update_time`) VALUES (1,'a','2017-12-22 15:27:18'), (2,'b','2017-12-22 15:27:18'), (3,'c','2017-12-22 15:27:18');DROP TABLE IF EXISTS `film`; CREATE TABLE `film` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(10) DEFAULT NULL, PRIMARY KEY (`id`), KEY `idx_name` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;INSERT INTO `film` (`id`, `name`) VALUES (3,'film0'),(1,'film1'),(2,'film2');DROP TABLE IF EXISTS `film_actor`; CREATE TABLE `film_actor` ( `id` int(11) NOT NULL, `film_id` int(11) NOT NULL, `actor_id` int(11) NOT NULL, `remark` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`), KEY `idx_film_actor_id` (`film_id`,`actor_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `film_actor` (`id`, `film_id`, `actor_id`) VALUES (1,1,1),(2,1,2), (3,2,1);

實(shí)踐(版本:5.7.30)

語法

在select 語句前加 explain 關(guān)鍵字。

explain select (select 1 from actor limit 1) from film;

輸出:

輸出結(jié)果屬性說明

id 列

id列的編號(hào)是 select 的序列號(hào),有幾個(gè) select 就有幾個(gè)id (不是絕對(duì)的,可能會(huì)優(yōu)化),并且id的順序是按 select 出現(xiàn)的順序 增長的。MySQL將 select 查詢分為簡單查詢(SIMPLE)和復(fù)雜查詢(PRIMARY)。 復(fù)雜查詢分為三類:簡單子查詢、派生表(from語句中的子查詢)、union 查詢。 id列越大執(zhí)行優(yōu)先級(jí)越高,id相同則從上往下執(zhí)行,id為NULL最后執(zhí)行。

示例 1:

explain select id from (select id from film) as der; explain select id + 1 as c from (select id from film) as der; explain select id ,name as c from (select id,name from film) as der;

輸出:

說明:3個(gè)語句的輸出,都只有1條記錄。由于第1個(gè)select查詢的 id 列在派生表中,并且是同一個(gè)表,所以優(yōu)化后,僅顯示1條記錄。

select_type 列

select_type 表示對(duì)應(yīng)行是簡單還是復(fù)雜的查詢,如果是復(fù)雜的查詢,又是上述三種復(fù)雜查詢中的哪一種。

1)、SIMPLE。前面已有示例。

2)、PRIMARY:復(fù)雜查詢中最外層的 select

3)、SUBQUERY:包含在 select 部分的子查詢(不在 from 子句中)

4)、DERIVED:包含在 from 子句中的子查詢。MySQL會(huì)將結(jié)果存放在一個(gè)臨時(shí)表中,也稱為派生 表。

5)、UNION:在 union 語句中的第二個(gè)union 和隨后的 select語句

6)、DEPENDENT SUBQUERY:表示這個(gè)subquery的查詢要受到外部表查詢的影響。where 語句中的子句也是SUBQUERY

7)、DEPENDENT UNION:UNION 被依賴。

示例 2:

explain select (select 1 from actor where id = 1) from (select * from film where id = 1) der;

輸出:

說明:from 子查詢 被優(yōu)化了,所以未顯示。

示例 3:

explain select * from ( select * from actor where id = 1 union all select * from actor where id = 2 ) a

輸出:

說明:derived2 表示 是第2條語句產(chǎn)生的派生表。

示例 4:

explain select (select name from actor where id = a.actor_id ) as name from (select * from film_actor where film_id =1 ) a

輸出:

示例 5:

explain select * from film_actor where actor_id in ( select id from actor where id = 1 union all select id from actor where id = 2 )

結(jié)果:

table 列

這一列表示 explain 的一行正在訪問哪個(gè)表。 當(dāng) from 子句中有子查詢時(shí),table列是 格式,表示當(dāng)前查詢依賴 id=N 的查詢,于

是先執(zhí)行 id=N 的查詢。

partitions 列

如果是分區(qū)表,則表示是哪個(gè)分區(qū)。

type 列

這一列表示關(guān)聯(lián)類型訪問類型,即MySQL決定如何查找表中的行,查找數(shù)據(jù)行記錄的大概范圍。

  • ALL:全表掃描

  • index:也是全表掃描。掃描表時(shí)按索引次序進(jìn)行,而不是行(即掃描索引的全部記錄,然后再查找記錄行)。

    它的主要優(yōu)點(diǎn)是:避免了排序。最大缺點(diǎn),按索引次序讀表有很大開銷。extra顯示“USING INDEX”表明使用覆蓋索引,不會(huì)再掃描數(shù)據(jù)表。

  • range:范圍掃描,一個(gè)有限制(部分?jǐn)?shù)據(jù))的索引掃描。范圍掃描通常出現(xiàn)在 in(), between ,> ,<, >= 等操作中。使用一個(gè)索引來檢索給定范圍 的行。

  • ref:也叫索引查找,返回所有匹配 某個(gè)單值的 行。相比 eq_ref,不使用唯一索引,而是使用普通索引或者唯一性索引的部分前綴,索引要和某個(gè)值相比較,可能會(huì)找到多個(gè)符合條件的行。

  • eq_ref:一種索引查找,最多只返回一條記錄。primary key 或 unique key 索引的所有部分被連接使用 ,最多只會(huì)返回一條符合條件

    的記錄。這可能是在 const 之外最好的聯(lián)接類型了,簡單的 select 查詢不會(huì)出現(xiàn)這種 type。

  • const,system:部分優(yōu)化轉(zhuǎn)成常量。用于 primary key 或 unique key 的所有列與常數(shù)比較時(shí),所以表最多有一

    個(gè)匹配行,讀取1次,速度比較快。system是const的特例,表里只有一條元組匹配時(shí)為system 。

  • NULL:在優(yōu)化階段就能返回值,例如 min,max。即通過數(shù)據(jù)庫記錄的統(tǒng)計(jì)數(shù)據(jù)進(jìn)行查詢,不真正查詢表。

依次從最優(yōu)到最差分別為:system > const > eq_ref > ref > range > index > ALL

一般來說,得保證查詢達(dá)到range級(jí)別,最好達(dá)到ref 。

示例 6:

explain select min(id ) from film ;

輸出:

示例 7:

explain select count(name ) from actor ; -- name沒有在索引中 explain select count(id ) from actor ; -- id 在索引中,聚集索引。 explain select count(name ) from film ; -- name 在索引中,非聚集索引。

輸出:

示例 8:

explain select * from actor where id > 1 ;

結(jié)果:

示例 9:

explain select * from actor where id =1;

結(jié)果:

示例 9:

explain select * from film_actor left join film on film_actor.film_id = film.id; explain select * from film where name = "film1";

輸出:

possible_keys 列

這一列顯示查詢可能使用哪些索引來查找。

explain 時(shí)可能出現(xiàn) possible_keys 有列,而 key 顯示 NULL 的情況,這種情況是因?yàn)楸碇袛?shù)據(jù) 不多,mysql認(rèn)為索引對(duì)此查詢幫助不大,選擇了全表查詢。

如果該列是NULL,則沒有相關(guān)的索引。在這種情況下,可以通過檢查 where 子句看是否可以創(chuàng)造一個(gè)適當(dāng)?shù)乃饕齺硖岣卟樵冃阅?#xff0c;然后用 explain 查看效果。

key 列

這一列顯示mysql實(shí)際采用哪個(gè)索引來優(yōu)化對(duì)該表的訪問。 如果沒有使用索引,則該列是 NULL。如果想強(qiáng)制mysql使用或忽視possible_keys列中的索引, 在查詢中使用 force index、ignore index。

key_len 列

這一列顯示了mysql在索引里使用的字節(jié)數(shù),通過這個(gè)值可以算出具體使用了索引中的哪些列。

ref 列

這一列顯示了在key列記錄的索引中,表查找值所用到的列或常量,常見的有:const(常量), 字段名(例:film.id)

rows 列

這一列是mysql 估計(jì) 要讀取并檢測(cè)的行數(shù),注意這個(gè)不是結(jié)果集里的行數(shù)。

Extra 列

這一列展示的是額外信息。常見的重要值如下:

  • Using index:查詢的列被索引覆蓋,并且where篩選條件是索引的前導(dǎo)列,是性能高的表現(xiàn)。一般是使用了覆蓋索引(索引包含了所有查詢的字段)。對(duì)于innodb來說,如果是覆蓋索引性能會(huì)有不少提高。
  • Using where:查詢的列未被索引覆蓋,where篩選條件非索引的前導(dǎo)列
  • Using where Using index:查詢的列被索引覆蓋,并且where篩選條件是索引列之一但是不是索引的前導(dǎo)列,意味著無法直接通過索引查找來查詢到符合條件的數(shù)據(jù)
  • NULL:查詢的列未被索引覆蓋,并且where篩選條件是索引的前導(dǎo)列,意味著用到了索引, 但是部分字段未被索引覆蓋,必須通過“回表”來實(shí)現(xiàn),不是純粹地用到了索引,也不是完全沒用到索引。
  • Using index condition:與Using where類似,查詢的列不完全被索引覆蓋,where條件中 是一個(gè)前導(dǎo)列的范圍;
  • Using temporary:mysql需要?jiǎng)?chuàng)建一張臨時(shí)表來處理查詢。出現(xiàn)這種情況一般是要進(jìn)行優(yōu)化的, 首先是想到用索引來優(yōu)化。

總結(jié)

以上是生活随笔為你收集整理的mysql explain实践的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。