偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

到底什么是MySQL執(zhí)行計(jì)劃嗎?

數(shù)據(jù)庫(kù) MySQL
當(dāng)我們工作到了一定的年限之后,一些應(yīng)該掌握的知識(shí)點(diǎn),我們是必須需要去了解的,比如今天面試官問(wèn)的SQL執(zhí)行計(jì)劃,看懂了這篇文章你就會(huì)知道這都不是事,讓我們一起來(lái)揭曉這里面的奧妙

[[395437]]

面試官說(shuō):工作這么久了,應(yīng)該知道sql執(zhí)行計(jì)劃吧,講講Sql的執(zhí)行計(jì)劃吧!看了看面試官手臂上紋的大花臂和一串看不懂的韓文,吞了吞口水,暗示自己鎮(zhèn)定點(diǎn),整理了一下思緒緩緩的對(duì)面試官說(shuō):我不會(huì)面試官:。。。。,回去等通知吧我:%^&%$!@#

一、前言

當(dāng)我們工作到了一定的年限之后,一些應(yīng)該掌握的知識(shí)點(diǎn),我們是必須需要去了解的,比如今天面試官問(wèn)的SQL執(zhí)行計(jì)劃當(dāng)我們執(zhí)行一條SQL的時(shí)候,可以直接對(duì)應(yīng)的結(jié)果,但是你并不曉得,它會(huì)經(jīng)歷多深遠(yuǎn)黑暗的隧道,通過(guò)連接器、查詢(xún)緩存、分析器、優(yōu)化器、執(zhí)行器重重篩選,才有可能展示到我們面前,有時(shí)候當(dāng)你等待N長(zhǎng)時(shí)間,但是展現(xiàn)的卻是 timeout,這個(gè)時(shí)候想砸電腦的心都有了,不過(guò)當(dāng)你看了今天的SQL執(zhí)行計(jì)劃后,你再也不用砸電腦了,看懂了這篇文章你就會(huì)知道這都不是事,讓我們一起來(lái)揭曉這里面的奧妙

在實(shí)際的應(yīng)用場(chǎng)景中,為了知道優(yōu)化SQL語(yǔ)句的執(zhí)行,需要查看SQL語(yǔ)句的具體執(zhí)行過(guò)程,以加快SQL語(yǔ)句的執(zhí)行效率。通常會(huì)使用explain+SQL語(yǔ)句來(lái)模擬優(yōu)化器執(zhí)行SQL查詢(xún)語(yǔ)句,從而知道m(xù)ysql是如何處理sql語(yǔ)句的。

官網(wǎng)地址: https://dev.mysql.com/doc/refman/5.5/en/explain-output.html

首先我們來(lái)下面的一條sql語(yǔ)句,其中會(huì)有 id、select_type、table等等這些列,這些就是我們執(zhí)行計(jì)劃中所包含的信息,我們要弄明白的就是這些列是用來(lái)干嘛的,以及每個(gè)列可能存在多少個(gè)值。

  1. explain select * from emp; 

 

二、執(zhí)行計(jì)劃中包含的信息

貼心的小農(nóng)已經(jīng)把sql復(fù)制出來(lái)了,只需要放到數(shù)據(jù)庫(kù)中執(zhí)行即可,方便簡(jiǎn)單快捷 ——牧小農(nóng)

建表語(yǔ)句:

  1. SET FOREIGN_KEY_CHECKS=0; 
  2. DROP TABLE IF EXISTS `dept`; 
  3. CREATE TABLE `dept` ( 
  4.   `DEPTNO` int NOT NULL
  5.   `DNAME` varchar(14) DEFAULT NULL
  6.   `LOC` varchar(13) DEFAULT NULL
  7.   PRIMARY KEY (`DEPTNO`) 
  8. ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 
  9.  
  10. INSERT INTO `dept` VALUES ('10''ACCOUNTING''NEW YORK'); 
  11. INSERT INTO `dept` VALUES ('20''RESEARCH''DALLAS'); 
  12. INSERT INTO `dept` VALUES ('30''SALES''CHICAGO'); 
  13. INSERT INTO `dept` VALUES ('40''OPERATIONS''BOSTON'); 
  14.  
  15. DROP TABLE IF EXISTS `emp`; 
  16. CREATE TABLE `emp` ( 
  17.   `EMPNO` int NOT NULL
  18.   `ENAME` varchar(10) DEFAULT NULL
  19.   `JOB` varchar(9) DEFAULT NULL
  20.   `MGR` int DEFAULT NULL
  21.   `HIREDATE` date DEFAULT NULL
  22.   `SAL` double(7,2) DEFAULT NULL
  23.   `COMM` double(7,2) DEFAULT NULL
  24.   `DEPTNO` int DEFAULT NULL
  25.   PRIMARY KEY (`EMPNO`), 
  26.   KEY `idx_job` (`JOB`), 
  27.   KEY `jdx_mgr` (`MGR`), 
  28.   KEY `jdx_3` (`DEPTNO`), 
  29.   KEY `idx_3` (`DEPTNO`) 
  30. ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 
  31.  
  32. INSERT INTO `emp` VALUES ('7369''SMITH''CLERK''7902''1980-12-17''800.00'null'20'); 
  33. INSERT INTO `emp` VALUES ('7499''ALLEN''SALESMAN''7698''1981-02-20''1600.00''300.00''30'); 
  34. INSERT INTO `emp` VALUES ('7521''WARD''SALESMAN''7698''1981-02-22''1250.00''500.00''30'); 
  35. INSERT INTO `emp` VALUES ('7566''JONES''MANAGER''7839''1981-02-02''2975.00'null'20'); 
  36. INSERT INTO `emp` VALUES ('7654''MARTIN''SALESMAN''7698''1981-09-28''1250.00''1400.00''30'); 
  37. INSERT INTO `emp` VALUES ('7698''BLAKE''MANAGER''7839''1981-01-05''2850.00'null'30'); 
  38. INSERT INTO `emp` VALUES ('7782''CLARK''MANAGER''7839''1981-09-06''2450.00'null'10'); 
  39. INSERT INTO `emp` VALUES ('7839''KING''PRESIDENT'null'1981-11-17''5000.00'null'10'); 
  40. INSERT INTO `emp` VALUES ('7844''TURNER''SALESMAN''7698''1981-09-08''1500.00''0.00''30'); 
  41. INSERT INTO `emp` VALUES ('7900''JAMES''CLERK''7698''1981-12-03''950.00'null'30'); 
  42. INSERT INTO `emp` VALUES ('7902''FORD''ANALYST''7566''1981-12-03''3000.00'null'20'); 
  43. INSERT INTO `emp` VALUES ('7934''MILLER''CLERK''7782''1982-01-23''1300.00'null'10'); 
  44.  
  45. DROP TABLE IF EXISTS `emp2`; 
  46. CREATE TABLE `emp2` ( 
  47.   `id` int NOT NULL AUTO_INCREMENT, 
  48.   `empno` int DEFAULT NULL
  49.   PRIMARY KEY (`id`) 
  50. ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; 
  51. INSERT INTO `emp2` VALUES ('1''111'); 
  52. INSERT INTO `emp2` VALUES ('2''222'); 
  53.  
  54. DROP TABLE IF EXISTS `salgrade`; 
  55. CREATE TABLE `salgrade` ( 
  56.   `GRADE` int NOT NULL
  57.   `LOSAL` double DEFAULT NULL
  58.   `HISAL` double DEFAULT NULL
  59.   PRIMARY KEY (`GRADE`) 
  60. ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 
  61.  
  62. INSERT INTO `salgrade` VALUES ('1''700''1200'); 
  63. INSERT INTO `salgrade` VALUES ('2''1201''1400'); 
  64. INSERT INTO `salgrade` VALUES ('3''1401''2000'); 
  65. INSERT INTO `salgrade` VALUES ('4''2001''3000'); 
  66. INSERT INTO `salgrade` VALUES ('5''3001''9999'); 
  67.  
  68. DROP TABLE IF EXISTS `t_job`; 
  69. CREATE TABLE `t_job` ( 
  70.   `id` int NOT NULL AUTO_INCREMENT, 
  71.   `job` varchar(9) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL
  72.   PRIMARY KEY (`id`), 
  73.   KEY `j` (`job`) 
  74. ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

2.1 id

select查詢(xún)的序列號(hào),包含一組數(shù)字,表示查詢(xún)中執(zhí)行select子句或者操作表的順序

id號(hào)分為三種情況:

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

  1. -- 左關(guān)聯(lián) 
  2. explain selectfrom emp e left join dept d on e.deptno = d.deptno; 
  3. -- 右關(guān)聯(lián)e 
  4. explain selectfrom emp e right join dept d on e.deptno = d.deptno; 

通過(guò)left join 和 right join 驗(yàn)證;id一樣(注意執(zhí)行計(jì)劃的table列),left join 先掃描e表,再掃描d表;right join 先掃描d表,再掃描e表

2、如果id不同,如果是子查詢(xún),id的序號(hào)會(huì)遞增,id值越大優(yōu)先級(jí)越高,越先被執(zhí)行

  1. explain select * from emp e where e.deptno = (select d.deptno from dept d where d.dname = 'SALES'); 

在下面的表中回先查詢(xún) id 為 2的數(shù)據(jù) 也就是我們的 d表(注意:我們可以看到d表中select_type為 SUBQUERY 也就是子查詢(xún)的 意思),然后根據(jù)d表中的deptno去查詢(xún) e表中的數(shù)據(jù)


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

  1. explain select * from emp e join dept d on e.deptno = d.deptno join salgrade sg on e.sal between sg.losal and sg.hisal where e.deptno = (select d.deptno from dept d where d.dname = 'SALES'); 

在這里先從id為2的執(zhí)行,如果id是一樣的,就按照順序執(zhí)行

2.2 select_type

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

  1. --simple:簡(jiǎn)單的查詢(xún),不包含子查詢(xún)和union 
  2. explain selectfrom emp; 

 

  1. --primary:查詢(xún)中若包含任何復(fù)雜的子查詢(xún),最外層查詢(xún)則被標(biāo)記為Primary 
  2. explain select * from emp e where e.deptno = (select d.deptno from dept d where d.dname = 'SALES'); 

 

  1. --union:若第二個(gè)select出現(xiàn)在union之后,則被標(biāo)記為union 
  2. explain select * from emp where deptno = 10 union select * from emp where sal >2000; 

 

  1. --dependent union:跟union類(lèi)似,此處的depentent表示union或union all聯(lián)合而成的結(jié)果會(huì)受外部表影響 
  2. explain select * from emp e where e.empno in ( select empno from emp where deptno = 10 union select empno from emp where sal >2000); 

 

  1. --union result:從union表獲取結(jié)果的select 
  2. explain select * from emp where deptno = 10 union select * from emp where sal >2000; 

 

  1. --subquery:在select或者where列表中包含子查詢(xún) 
  2. explain selectfrom emp where sal > (select avg(sal) from emp) ; 

 

  1. --dependent subquery:subquery的子查詢(xún)要受到外部表查詢(xún)的影響 
  2. explain select * from emp e where e.deptno = (select distinct deptno from dept where deptno = e.deptno); 

 

  1. --DERIVED: from子句中出現(xiàn)的子查詢(xún),也叫做派生類(lèi), 
  2. explain select * from (select ename staname,mgr from emp where ename = 'W' union select ename,mgr from emp where ename = 'E') a; 

 

  1. -- UNCACHEABLE SUBQUERY:表示使用子查詢(xún)的結(jié)果不能被緩存 
  2. explain select * from emp where empno = (select empno from emp where deptno=@@sort_buffer_size); 

 

  1. --uncacheable union:表示union的查詢(xún)結(jié)果不能被緩存 
  2. explain select * from emp where exists (select 1 from dept where emp.deptno = dept.deptno union select 1 from dept where deptno = 10); 

 

2.3 table

對(duì)應(yīng)行正在訪問(wèn)哪一個(gè)表,表名或者別名,可能是臨時(shí)表或者union合并結(jié)果集 1、如果是具體的表名,則表明從實(shí)際的物理表中獲取數(shù)據(jù),也可以是表的別名

  1. explainselect*fromempwheresal>(selectavg(sal)fromemp); 

2、表名是derivedN的形式,表示使用了id為N的查詢(xún)產(chǎn)生的衍生表

  1. explain select * from (select ename staname,mgr from emp where ename = 'WARD' union select ename staname,mgr from emp where ename = 'SMITH') a; 

derived2 :表明我們需要從衍生表2中取數(shù)據(jù)

3、當(dāng)有union result的時(shí)候,表名是union n1,n2等的形式,n1,n2表示參與union的id

  1. explain select * from emp where deptno = 10 union select * from emp where sal >2000; 

 

2.4 type

type顯示的是訪問(wèn)類(lèi)型,訪問(wèn)類(lèi)型表示我是以何種方式去訪問(wèn)我們的數(shù)據(jù),最容易想的是全表掃描,直接暴力的遍歷一張表去尋找需要的數(shù)據(jù),效率非常低下,訪問(wèn)的類(lèi)型有很多,效率從最好到最壞依次是:

  1. system > const > eqref > ref > fulltext > refornull > indexmerge > uniquesubquery > indexsubquery > range > index > ALL 

一般情況下,得保證查詢(xún)至少達(dá)到range級(jí)別,最好能達(dá)到ref

  1. --all:全表掃描,一般情況下出現(xiàn)這樣的sql語(yǔ)句而且數(shù)據(jù)量比較大的話(huà)那么就需要進(jìn)行優(yōu)化。 
  2. explain select * from emp; 

 

  1. --index:全索引掃描這個(gè)比all的效率要好,主要有兩種情況,一種是當(dāng)前的查詢(xún)時(shí)覆蓋索引,即我們需要的數(shù)據(jù)在索引中就可以索取,或者是使用了索引進(jìn)行排序,這樣就避免數(shù)據(jù)的重排序 
  2. explain select empno from emp; 

 

  1. --range:表示利用索引查詢(xún)的時(shí)候限制了范圍,在指定范圍內(nèi)進(jìn)行查詢(xún),這樣避免了index的全索引掃描,適用的操作符:=, <>, >, >=, <, <=, IS NULL, BETWEEN, LIKE, or IN()  
  2. explain select * from emp where empno between 7000 and 7500; 

 

  1. --index_subquery:利用索引來(lái)關(guān)聯(lián)子查詢(xún),不再掃描全表 
  2. explain select * from emp where emp.job in (select job from t_job); 
  3.  
  4. --unique_subquery:該連接類(lèi)型類(lèi)似與index_subquery,使用的是唯一索引  
  5. explain select * from emp e where e.deptno in (select distinct deptno from dept); 
  6.  
  7. --ref_or_null:對(duì)于某個(gè)字段即需要關(guān)聯(lián)條件,也需要null值的情況下,查詢(xún)優(yōu)化器會(huì)選擇這種訪問(wèn)方式 
  8. explain select * from emp e where  e.mgr is null or e.mgr=7369; 

 

  1. --ref:使用了非唯一性索引進(jìn)行數(shù)據(jù)的查找 
  2. create index idx_3 on emp(deptno); 
  3. explain select * from emp e,dept d where e.deptno =d.deptno; 

 

  1. --eq_ref :使用唯一性索引進(jìn)行數(shù)據(jù)查找 
  2. explain select * from emp,emp2 where emp.empno = emp2.empno; 

 

  1. --const:這個(gè)表至多有一個(gè)匹配行, 
  2. explain select * from emp where empno = 7369; 

 

  1. --system:表只有一行記錄(等于系統(tǒng)表),這是const類(lèi)型的特例,平時(shí)不會(huì)出現(xiàn) 

2.5 possible_keys

顯示可能應(yīng)用在這張表中的索引,一個(gè)或多個(gè),查詢(xún)涉及到的字段上若存在索引,則該索引將被列出,但不一定被查詢(xún)實(shí)際使用

  1. explain select * from emp,dept where emp.deptno = dept.deptno and emp.deptno = 10; 

 

2.6 key

實(shí)際使用的索引,如果為null,則沒(méi)有使用索引,查詢(xún)中若使用了覆蓋索引,則該索引和查詢(xún)的select字段重疊。

  1. explain select * from emp,dept where emp.deptno = dept.deptno and emp.deptno = 10; 

 

2.7 key_len

表示索引中使用的字節(jié)數(shù),可以通過(guò)keylen計(jì)算查詢(xún)中使用的索引長(zhǎng)度,在不損失精度的情況下長(zhǎng)度越短越好。

1、一般地,keylen 等于索引列類(lèi)型字節(jié)長(zhǎng)度,例如int類(lèi)型為4 bytes,bigint為8 bytes;

2、如果是字符串類(lèi)型,還需要同時(shí)考慮字符集因素,例如utf8字符集1個(gè)字符占3個(gè)字節(jié),gbk字符集1個(gè)字符占2個(gè)字節(jié)

3、若該列類(lèi)型定義時(shí)允許NULL,其keylen還需要再加 1 bytes

4、若該列類(lèi)型為變長(zhǎng)類(lèi)型,例如 VARCHAR(TEXT\BLOB不允許整列創(chuàng)建索引,如果創(chuàng)建部分索引也被視為動(dòng)態(tài)列類(lèi)型),其keylen還需要再加 2 bytes 字符集會(huì)影響索引長(zhǎng)度、數(shù)據(jù)的存儲(chǔ)空間,為列選擇合適的字符集;變長(zhǎng)字段需要額外的2個(gè)字節(jié),固定長(zhǎng)度字段不需要額外的字節(jié)。而null都需要1個(gè)字節(jié)的額外空間,所以以前有個(gè)說(shuō)法:索引字段最好不要為NULL,因?yàn)镹ULL讓統(tǒng)計(jì)更加復(fù)雜,并且需要額外一個(gè)字節(jié)的存儲(chǔ)空間。

  1. explain select * from emp,dept where emp.deptno = dept.deptno and emp.deptno = 10; 

 

2.8 ref

顯示索引的哪一列被使用了,如果可能的話(huà),是一個(gè)常數(shù)

  1. explain select * from emp,dept where emp.deptno = dept.deptno and emp.deptno = 10; 

 

2.9 rows

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

  1. explain select * from emp; 

 

2.10 extra

包含額外的信息。

  1. --using filesort:說(shuō)明mysql無(wú)法利用索引進(jìn)行排序,只能利用排序算法進(jìn)行排序,會(huì)消耗額外的位置 
  2. explain select * from emp order by sal; 

 

  1. --using temporary:建立臨時(shí)表來(lái)保存中間結(jié)果,查詢(xún)完成之后把臨時(shí)表刪除 
  2. explain select ename,count(*) from emp where deptno = 10 group by ename; 

 

  1. --using index:這個(gè)表示當(dāng)前的查詢(xún)時(shí)覆蓋索引的,直接從索引中讀取數(shù)據(jù),而不用訪問(wèn)數(shù)據(jù)表。如果同時(shí)出現(xiàn)using where 表名索引被用來(lái)執(zhí)行索引鍵值的查找,如果沒(méi)有,表面索引被用來(lái)讀取數(shù)據(jù),而不是真的查找 
  2. explain select deptno,count(*) from emp group by deptno limit 10; 

 

  1. --using where:使用where進(jìn)行條件過(guò)濾 
  2. explain select * from emp2 where empno = 1; 

 

三 總結(jié)

到這里執(zhí)行計(jì)劃就講完了,sql的執(zhí)行計(jì)劃并不是很難,主要是記住每個(gè)列代表的意思和如何進(jìn)行優(yōu)化,這個(gè)是需要大量的訓(xùn)練和實(shí)操實(shí)現(xiàn)的, 有興趣的小伙伴可以自行去試試,還是很有趣的,本文只是簡(jiǎn)單介紹一下MySQL執(zhí)行計(jì)劃,想全面深入了解MySQL,可優(yōu)先閱讀MySQL官方手冊(cè),大家加油~

 

責(zé)任編輯:姜華 來(lái)源: 牧小農(nóng)
相關(guān)推薦

2022-02-15 07:36:21

SQLEXPLAIN數(shù)據(jù)庫(kù)

2023-09-21 10:55:51

MysqlSQL語(yǔ)句

2021-05-28 10:46:36

MySQL執(zhí)行計(jì)劃

2022-11-02 15:28:55

MySQL執(zhí)行計(jì)劃B+樹(shù)

2024-09-12 15:16:14

2022-08-08 08:03:44

MySQL數(shù)據(jù)庫(kù)CBO

2011-09-14 17:03:17

數(shù)據(jù)庫(kù)執(zhí)行計(jì)劃解析

2022-12-13 08:36:42

D-SMARTOracle數(shù)據(jù)庫(kù)

2020-09-15 08:44:57

MySQL慢日志SQL

2024-04-19 13:17:40

PostgreSQLSQL數(shù)據(jù)庫(kù)

2015-04-22 14:17:45

SQL SERVERMSSQL SERVE緩沖區(qū)

2021-03-17 09:35:51

MySQL數(shù)據(jù)庫(kù)explain

2009-11-13 16:28:02

Oracle生成執(zhí)行計(jì)

2018-02-27 14:00:35

數(shù)據(jù)庫(kù)MySQL統(tǒng)計(jì)信息

2017-11-15 08:50:59

數(shù)據(jù)庫(kù)MySQL執(zhí)

2022-08-15 15:09:26

SQL數(shù)據(jù)庫(kù)MySQL

2009-11-10 16:00:05

Oracle執(zhí)行計(jì)劃

2021-09-07 10:43:25

EverDB分布式執(zhí)行

2015-12-01 13:33:51

UnikernelLinux運(yùn)維

2010-04-16 09:27:18

Ocacle執(zhí)行計(jì)劃
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)