1. 程式人生 > 其它 >Mysql效能優化總結-04執行計劃

Mysql效能優化總結-04執行計劃

技術標籤:mysqlmysql資料庫

1.建測試表

教師表
DROP TABLE IF EXISTS `teacher`;
CREATE TABLE `teacher` (
  `tid` int(3) DEFAULT NULL,
  `tname` varchar(20) DEFAULT NULL,
  `tcid` int(3) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
插入資料
INSERT INTO `teacher` VALUES ('1', 'mashibing', '1');
INSERT INTO `teacher` VALUES ('2', 'james', '2');
INSERT INTO `teacher` VALUES ('3', 'lewis', '3');
課程表
DROP TABLE IF EXISTS `course`;
CREATE TABLE `course` (
  `cid` int(3) DEFAULT NULL,
  `cname` varchar(20) DEFAULT NULL,
  `tid` int(3) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
插入資料
INSERT INTO `course` VALUES ('1', 'mysql', '1');
INSERT INTO `course` VALUES ('2', 'jvm', '1');
INSERT INTO `course` VALUES ('3', 'java', '2');
INSERT INTO `course` VALUES ('4', 'spring', '3');

教師聯絡表
DROP TABLE IF EXISTS `teacher_contact`;
CREATE TABLE `teacher_contact` (
  `tcid` int(3) DEFAULT NULL,
  `phone` varchar(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
插入資料
INSERT INTO `teacher_contact` VALUES ('1', '15888888888');
INSERT INTO `teacher_contact` VALUES ('2', '18888888888');
INSERT INTO `teacher_contact` VALUES ('3', '19999999999');

2.explain分析sql

id 是查詢序列編號,每張表都是單獨訪問的,一個select就會有一個序號。

id值不同的時候:

id值不同的時候,先查詢id值大的(先大後小)。

-- 查詢mysql課程的老師的手機號
EXPLAIN extended select 
tc.phone
from teacher_contact tc
where tcid=(
	select tcid from teacher t
  where t.tid=(
		select c.tid FROM course c
		where c.cname='mysql' 
	)
)

執行計劃:
在這裡插入圖片描述
查詢順序:cource c ——teacher t——teacher_concact tc
  先查課程表,再查教師表,最後查教師聯絡表。子查詢只能以這種方式查詢,拿到內層結果後才能進行外層查詢。

id值相同的時候:

--查詢課程ID為2,或者聯絡表id為3的老師
EXPLAIN extended 
select t.tname,c.cname,tc.phone
  from teacher t ,course c ,teacher_contact tc
where t.tid=c.cid
  and t.tcid=tc.tcid
  and (c.cid=2 or tc.tcid=3)

執行計劃:
在這裡插入圖片描述
  id值相同時,表的查詢順序是從上往下順序執行。例如這次查詢的id都是1(說明子查詢被優化器轉換成了連線查詢),查詢的順序是teacher t(3條),teacher_contact tc(3條),course c(4條)。
  在連線查詢中,先查詢的叫做驅動表,後查詢的叫做被驅動表。
  應該把小表放在前面查詢,因為他的中間結果最少(小表驅動大表思想)。

id既有相同,也有不同

  就是id不同的先大後小,id相同的從上往下。

3.explain詳解

1.select type

列舉一些常見的查詢型別
SIMPLE
  簡單查詢,不包含子查詢,不包含union。

EXPLAIN SELECT * FROM teacher;

在這裡插入圖片描述
包含子查詢的案例

-- 查詢mysql課程的老師的手機號
EXPLAIN extended select 
tc.phone
from teacher_contact tc
where tcid=(
	select tcid from teacher t
  where t.tid=(
		select c.tid FROM course c
		where c.cname='mysql' 
	)
)

在這裡插入圖片描述

PAIMARY
  子查詢sql 語句中的主查詢,也就是最外面的那層查詢。

SUBQUERY
  子查詢中所有的內層查詢都是SUBQUERY型別。

DERIVED
   衍生查詢,表示在得到最終查詢結果前,會用到臨時表。例如:
在這裡插入圖片描述
這裡先執行了UNION查詢,後進行了DERIVED查詢。
UNION
  用到了UNION查詢,同上。
UNION RESULT
  顯示哪些表之間存在UNION查詢。<union2,3>代表course表id為2,3的查詢存在UNION。同上例。
  這裡沒有列舉全部的select_type,還有dependent union、dependent subquery、materialized、uncacheable subquery、uncacheable union。

2.TYPE連線型別

  連線型別常見連線型別效能排序:system>const>rq_ref>ref>range>index>all。
這裡沒列舉全,還有fulltext、ref_or_null、index_merge、unique_subquery、index_subquery。
  以上連線型別除了all都能用到索引。

型別出現條件
const主鍵索引或者唯一索引,只能查到一條資料的sql。
systemsystem是const的一種特例,只有一行滿足條件,對於MyISAM,Memory的表,只查詢到一條記錄,也是system。

eq_ref

   通常出現在多表關聯查詢,被驅動表通過唯一性索引(unique或primary key)進行訪問,此時被驅動表的訪問方式就是eq_ref。
   eq_ref是除const外最好的訪問型別。
teacher_contact tcid欄位上加上主鍵,

執行sql
EXPLAIN extended  
select t.tcid 
from teacher t,teacher_contact tc 
where t.tcid=tc.tcid

計劃如下:
在這裡插入圖片描述

小結:

   以上3種,system,const,eq_ref,都是可遇不可求的,很難優化到這個狀態。

ref

   查詢用到了非唯一索引,或者關聯操作只使用了索引最左字首。

teacher表tcid欄位加索引,然後執行sql

EXPLAIN extended  
select t.tcid 
from teacher t
where t.tcid=2

在這裡插入圖片描述

range

   索引範圍掃描。
   如果where後面是between and 或 < 或 >或 <= 或 >=或in這些,type型別就為range。

teacher 表tid加索引,執行

EXPLAIN extended  
select t.tcid 
from teacher t
where t.tid < 3

在這裡插入圖片描述
 &emspin查詢也可能是range。這裡不舉例子(PS:我這裡試過了是index)

index

  執行sql
 &emspteacher; 表tid欄位有索引。

EXPLAIN extended  
select t.tid 
from teacher t

在這裡插入圖片描述
   full index scan,索引全掃描,比不走索引快。

all

full table scan,全表掃描,如果沒有索引或者沒用到索引,type就是index。

NULL

不用訪問表或者索引就能得到結果,例如:
explain select 1 from dual where 1=1;

小結:

   一般來說,需要保證查詢的type至少達到range級別,最好能達到 ref。
   all全表掃描,和index 都是可以優化的,視情況而定,和資料量有關係,資料量影響優化器的選擇,優化器會選擇成本低的執行計劃。

其他的欄位解讀略。