1. 程式人生 > 資料庫 >MySQL調優

MySQL調優

一、檢視

1.1 檢視的概念

​ 檢視是基於一個表或多個表或檢視的邏輯表,本身不包含資料,通過它可以對錶裡面的資料進行查詢和修改。檢視基於的表成為基表。檢視是儲存在資料字典裡面的一條select語句。通過建立檢視可以提取資料的邏輯上的集合或組合

1.2 檢視的優點

1、對資料庫的訪問,因為檢視可以有選擇性的選取資料庫裡的一部分

2、可以把複雜的查詢變得簡單

3、維護資料的獨立性,檢視可以從多個表檢索資料

4、對於相同的資料可以產生不同的檢視

5、可以對許可權進行控制

1.3 檢視的建立

CREATE VIEW 檢視名稱 AS 子查詢

如:建立一張基本工資大於2000元的員工資訊檢視

create 	view view2 as select * from emp where sal > 2000;

建立一張可以統計部門編號,部門名稱,部門人數,部門平均工資的檢視

create view ad view3 as select
	d.deptno,
	d.dname,
	count(e.deptno),
	IFNULL(round(avg(e.sal),2),0)
FROM
	emp e
right join dept d on (e.deptno = d.deptno)
GROUP BY
	e.deptno

1.4 檢視的使用

查詢檢視語法:

SELECT * FROM 檢視名稱

SELECT * FROM  findAll

1.5 修改檢視

語法:

create or replace view 檢視名稱 as 檢視語句

或者

alterview 檢視名稱 as 查詢語句

該語句用於更改已有檢視的定義。其語法與CREATE VIEW類似。當檢視不存在時建立,存在時進行修改

1.6 刪除檢視

如果一個檢視不再使用時,可以直接通過DROP命令進行刪除

drop view 檢視名稱

1.7 檢視檢視定義

語法:DESC 檢視名稱

二、索引

2.1 概念

索引是一種特殊的檔案,它們包含著對資料表裡所有記錄的引用指標。資料庫索引是資料庫管理系統中一個排序的資料結構,以協助快速查詢、更新資料庫表中的資料。索引的實現通常是使用B樹以及變種B+樹

​ 索引用來加快資料的檢索,類似於書籍的索引。在資料庫中索引可以減少資料庫程式查詢結果時需要讀取的資料量,類似於在書籍中,我們利用索引可以不用翻閱整本書即可找到想要的內容。

2.2 索引的型別

主鍵索引:資料列不允許重複,不允許為NULL,一個表中只能有一個主鍵

唯一索引:資料列不允許重複,允許為NULL值,一個表中允許多個列建立唯一索引

單值索引:給表中的某一個欄位新增索引

組合索引:給表中的多個欄位新增索引,主要針對的是條件查詢

注:還有一個全文索引,用的很少,這裡就不做介紹

2.3 索引的建立

建立唯一索引

alter table 表名 add UNIQUE(列名)

建立單值索引

alter table 表名 add index 索引名稱(列名)

組合索引

alter table 表名 add index 索引名稱(列名1,列名2,...)

-- 給emp表中的sql欄位新增索引
alter table emp add index sal_index(sal)

2.4 查詢索引

查詢某張表中已經存在的索引

語法:show index from 表名

2.5 刪除索引

語法:alter table 表名 drep 索引名

-- 刪除emp表中的sal_index索引
alter tabel emp drop index sal_index	

2.6 索引的優點和缺點

優點:

​ 可以大大加快資料的檢索速度,這也是建立索引的最主要的原因

缺點

​ 時間方面:建立索引和維護索引需要耗費時間,具體的,當對錶中的資料進行新增,刪除,修改的時候,索引也是需要動態維護的,會降低增刪改的執行效率

​ 空間方面:索引需要佔用實體記憶體空間

2.7 索引的基本原理

​ 索引用來快速地尋找那些具有特定值的記錄。如果沒有索引,一般來說執行查詢時遍歷整張表。索引的原理很簡單,就是把無序的資料變成有序的查詢

1、把建立了索引的列的內容進行排序

2、對排序結果生成倒排表

3、在倒排表內容上拼上資料地址鏈

4、在查詢的時候,先拿到倒排表內容,再取出資料地址鏈,從而拿到具體資料

2.8 建立資料的原則

給欄位新增索引是為了提高查詢效率,但不是所有的欄位都可以新增索引,建立索引有以下特點。

​ 1、在經常需要搜尋的列上,可以加快搜索的速度

​ 2、在作為主鍵的列上,強制該列的唯一性和組織表中資料的排列結構

​ 3、在經常用在連線的列上,這些列主要是一些外來鍵,可以加快連線的速度;

​ 4、在經常需要排序的列上建立索引,因為索引已經排序,這樣查詢可以利用索引的排序,加快排序查詢時間;

​ 5、更新頻繁的欄位不建議設定索引

​ 6、 儘量的擴充套件索引,不要新建索引。比如表中已經有a的索引,現在要加(a,b)的索引,那麼只需要修改原來的索引即可。

​ 7、對於那些查詢中很少涉及的列,重複值比較多的列不要建立索引

​ 8、對於定.義為text、image和bit的資料型別的列不要建立索引

試驗程式碼

-- 查看錶結構
DESC USER

-- 查詢表中存在的索引
SHOW INDEX FROM USER

-- 給表中username新增唯一索引,欄位本身是唯一的就適合新增唯一索引
ALTER TABLE USER ADD UNIQUE(username);

-- 給表中password新增單值索引,查詢或者關聯較多的欄位適合新增單值索引
ALTER TABLE USER ADD INDEX password_index(PASSWORD)

-- 給表中新增多值索引,多個查詢組合查詢
ALTER TABLE USER ADD INDEX sex_age_index(sex,age)

-- 刪除索引
ALTER TABLE USER DROP INDEX username
 
-- 建立觸發器在user新增後備份到表user2中
CREATE TRIGGER user_tri 
AFTER 
INSERT ON USER 
FOR EACH ROW 
INSERT INTO user2(username) VALUES(new.username);

-- 測試觸發器
INSERT INTO USER(username,PASSWORD,age,sex) VALUES('admin','123',18,1)

-- 查詢觸發器
SHOW TRIGGERS

-- 刪除觸發器
DROP TRIGGER user_tri

-- user資料修改後,user2同步修改,usre3將原來值進儲存  這裡Mysql5.5還不支援
DELIMITER//
CREATE TRIGGER user_tri2
AFTER 
UPDATE ON USER
FOR EACH ROW
BEGIN
INSERT INTO user2(username,PASSWORD,age,sex) VALUES(new.username,new.password,new.age,new.sex);
INSERT INTO user3(username,PASSWORD,age,sex) VALUES(old.username,old.password,old.age,old.sex);
END//
DELIMITER

三、觸發器

3.1 概念

​ 在MySQL裡面也就是對某一個表的一定的操作,觸發某種條件(Insert,Update,Delete 等)就會自定執行一些程式。和web中的監聽器很像

3.2 觸發器的建立

觸發器語法:

create trigger 觸發器名稱
觸發時機 
觸發事件 on 表名 
for each row
觸發器程式體

觸發器解釋:

​ 觸發器名稱:標識觸發器名稱,使用者自行定義

​ 觸發時機:可取值為BEFORE或者、UPDATE、DELETE

​ 觸發事件:取值為INSERT、UPDATE或DELETE

​ 表名:標識建立觸發器的表名,即是在那張表上建立的觸發器

​ 觸發器程式體:可以是一句SQL語句,或者用BEGIN和END包含多條語句

例如:現有兩張表t1,t2,兩張表中都有id,name欄位,新加t1表記錄後自動新增到t2中

create trigger trigger1
after
insert on t1
for each row
insert into t2(name) valus(new.name);
-- 說明:new值的是新增的新值,OLE指的是更新或者刪除的舊值
-- INSERT只有NEW  UPDATE有NEW和OLD
-- DELETE只有OLD

注:一般情況下,Mysql預設是以;號作為結束執行語句。為了解決這個問題,可以用到delimiter語句。例如delimiter //,可以將結束符號變成//,建立完觸發器後再執行delimiter ;將結束符號改回成;號

例如:

delimiter//
create trigger trigger2
after
update on t1
for each row
begin
insert into t2(name) value(new.name);
insert into t3(name) value(old,name);
end//
delimiter

3.3 檢視觸發器

語法:

show trigger

3.4 刪除觸發器

語法

drop trigger 觸發器名稱

四、儲存過程(未完善)

4.1 概念

​ 儲存過程是能完成一定操作的一組SQL語句,它在建立後以被有權使用者在任何需要的地方呼叫。

​ 通過使用過程,不僅可以簡化客戶端應用程式的開發和維護,而且可以提高應用程式的執行效能。(假如某應用程式需要經常向某張表中插入資料,並且在插入資料時需要對資料進行檢查驗證,為了簡化客戶端的維護,可以使用儲存過程)

4.2 建立儲存過程

語法:

create procedure 儲存過程名稱
(
	[IN] 引數1引數型別,
	OUT引數2 引數型別
)
BEGIN
 程式程式碼塊
END;

IN:代表輸入引數(如果沒有註明, 引數預設的型別為 in)

OUT:輸出引數,不管有沒有傳值裡面都是null

IN OUT;既可以做為輸入引數,也可以做為輸出引數

MySQL 儲存過程名字後面的“()”是必須的,即使沒有一個引數,也需要“()”

五、MySQL的結構體系

5.1 MySQL的核心配置檔案檢視位置

配置中的一些核心配置

[mysqld]

# socket=MYSQL

# The TCP/IP Port the MySQL Server will listen on
port=3306

# Path to installation directory. All paths are usually resolved relative to this.
# basedir="C:/Program Files/MySQL/MySQL Server 5.6/"

# Path to the database root
datadir=C:/ProgramData/MySQL/MySQL Server 5.6/Data

# The default character set that will be used when a new schema or table is
# created and no character set is defined
character-set-server=utf8

# The default storage engine that will be used when create new tables when
default-storage-engine=INNODB

5.2 MySQL的體系架構

元件說明:

1、MySQL向外提供的互動介面(Connectors)

2、連線池元件(Connection Pool)

3、管理服務元件和工具元件(Management Service & Utilities)

  • 主要負責資料的備份,資料庫的叢集,認證,許可權,查詢索引等

4、SQL介面元件(SQL Interface)

  • 負責接收SQL命令,判斷SQL的型別是DML還是DDL還是檢視等

5、查詢分析元件(Parser)

  • 負責語法解析,就是我們的SQL語句,在這裡進行語法的檢查,語法檢查失敗直接返回語法錯誤。
  • 語義解析,比如查詢的某張的表不存在直接返回xx表不存在。

6、優化器元件(Optimizer)

  • 對SQL命令進行優化,SQL的優化主要就是針對這塊
  • MySQLServer會對傳送過來的SQL語句進行優化,根據sql語句,生成一系列的執行計劃,然後從執行計劃選出最優的一條計劃執行。
  • 在這裡判斷是否使用索引,如何使用索引

7、快取檔案(Caches & Buffers)

  • 查詢快取:主要對SQL語句快取,把經常使用的SQL語句快取起來
  • 資料快取:從磁碟中載入資料到內容中,然後對記憶體中的資料進行過濾
  • 日誌快取:通過日誌快取恢復記錄 這裡就是undo和redo

8、外掛式儲存引擎(Pluggable Storage Engines)

9、物理檔案(File System)

5.3 查詢一條SQL語句的過程

MySQL的Query Profiler是一個使用非常方便的Query 診斷分析工具,通過該工具可以獲取一條Query 在整個執行過程中多種資源的消耗情況,如 CPU,IO,IPC,SWAP 等,以及發生的 PAGE FAULTS,CONTEXT SWITCHE 等等,同時還能得到該 Query 執行過程中 MySQL 所呼叫的各個函式在原始檔中的位置。

5.3.1 檢視 profiling 引數
show variables like '%profi%';

profiling 預設是關閉的,所以需要手動開啟

5.3.2 開啟profiling

執行查詢語句,每執行一次SQL語句都會生成一條profiling記錄

select * from t_user where id = 2

檢視所有sql的profiles

show profiles

查詢單個sql的profiles

show profile cpu for query 6;

1.show profile預設是關閉的,並且開啟後只存活於當前會話,也就說每次使用前都需要開啟。

2.通過show profiles檢視sql語句的耗時時間,然後通過show profile命令對耗時時間長的sql語句進行診斷。

3.注意show profile診斷結果中出現相關欄位的含義,判斷是否需要優化sql語句。

5.4 MySQL的儲存結構

資料庫儲存引擎是資料庫底層軟體組織,資料庫管理系統(DBMS)使用資料引擎進行建立、查詢、更新和刪除資料。不同的儲存引擎提供不同的儲存機制、索引技巧、鎖定水平等功能,使用不同的儲存引擎,還可以 獲得特定的功能。現在許多不同的資料庫管理系統都支援多種不同的資料引擎。MySQL的核心就是儲存引擎。

常用的儲存引擎有以下:

  • Innodb引擎:Innodb引擎提供了對資料庫ACID事務的支援。並且還提供了行級鎖和外來鍵的約束。它的設計的目標就是處理大資料容量的資料庫系統。MySQL預設值的儲存引擎。
  • MyIASM引擎:不提供事務的支援,也不支援行級鎖和外來鍵。

查詢所有儲存引擎

5.4.1 MyISAM與InnoDB對比
MyISAM Innodb
儲存結構* 每張表被存放在三個檔案:
frm-表結構定義、
MYD(MYData)-資料檔案、
MYI(MYIndex)-索引檔案
所有的表都儲存在同一個資料檔案中,
InnoDB表的大小隻受限於作業系統檔案的大小,
一般為2GB
儲存空間* MyISAM可被壓縮,儲存空間較小 InnoDB的表需要更多的記憶體和儲存,
它會在主記憶體中建立其專用的緩衝池用於高速緩衝資料和索引
檔案格式 資料和索引是分別儲存的,資料.MYD,索引.MYI 資料和索引是集中儲存的,.ibd
記錄儲存順序 按記錄插入順序儲存 按主鍵大小有序插入
外來鍵* 不支援 支援
事務* 不支援 支援
鎖支援* 表級鎖定 行級鎖定、表級鎖定,鎖定力度小併發能力高
SELECT* MyISAM更優
INSERT、UPDATE、DELETE InnoDB更優
索引的實現方式 B+樹索引,myisam 是堆表 B+樹索引,Innodb 是索引組織表
雜湊索引 不支援 支援
全文索引 支援 支援(MySQL5.6之前不支援)

總結:

Innodb(MySQL預設的):

  • 支援事務和外來鍵
  • 磁碟的儲存檔案只有一個
  • 支援表和行的級鎖

MyISAM:

  • 不支援事務和外來鍵
  • 磁碟的儲存檔案有三個,佔用磁碟空間少,會對檔案進行壓縮
  • 只支援表鎖
5.4.2 引擎的選擇

如果沒有特別的需求,使用預設的Innodb即可。
MyISAM:查詢效率高,儲存空間小。
Innodb:更新(刪除)操作頻率也高,或者要保證資料的完整性;併發量高,支援事務和外來鍵。。
實際業務中可以使用觸發器來實現同步到兩張表,寫用Innodb,查詢用MyISAM

七、資料庫的SQL執行計劃

7.1 EXPLAIN SQL執行計劃

​ EXPLAIN命令是檢視查詢優化器如何決定執行查詢的主要方法,使用EXPLAIN,只需要在查詢中SELECT關鍵字之前增加EXPLAIN關鍵字即可,MySQL會在查詢上設定一個標記,當執行查詢時,這個標記會使其返回關於在執行計劃中每一步的資訊,而不是執行它,它會返回一行或者多行資訊,顯示出執行計劃中的每一部分和執行的次序,從而可以從分析結果中找到查詢語句或是表結構的效能瓶頸。

7.2 EXPLAIN的作用

1、分析出表的讀取順序

2、資料讀取操作的操作型別

3、檢視哪些索引可以使用

4、檢視哪些索引在查詢的時候被實際使用到

5、表之間的引用

6、檢視每張表有多少行被優化器查詢

7.3 EXPLAIN的使用

explain select * from t_user;

7.4 查詢的結果引數含義

7.4.1 ID

每個select子句的標識id,代表執行select子句或操作表的順序,id約大,越先執行,id相同,執行順序由上至下

-- id約大,越先執行
EXPLAIN
select * from t_user u1 where u1.id =(
select u.id from t_user u where u.id = 2)

-- id相同,執行順序由上至下
EXPLAIN
select * from t_user u1 where u1.id in(
select u.id from t_user u where u.id = 2)

-- id相同和不同,同時存在,遵從優先順序高的優先執行,優先順序相同的按照由上至下的順序執行
EXPLAIN
select * from t_user u1,t_user u2 where u1.id =(
select u.id from t_user u where u.id = 2)

7.4.2 select_type(查詢型別)

查詢的型別,主要用於區別普通查詢,聯合查詢,子查詢等複雜查詢

  • simple:簡單的select查詢,查詢中不包含子查詢或union查詢
  • primary:查詢中若包含任何複雜的子部分,最外層查詢會被標記為primary
  • subquery:在select或where列表中包含了子查詢
  • derived:在from列表中包含的子查詢被標記為derived,mysql會遞迴將這些子查詢,把結果放在一張臨時表中
  • union:若第二個select出現在union之後,則被標記為union,若union包含在from子句的子查詢中,外層select將被標記為derived
  • union result :union之後的結果集產生
-- 臨時表
explain
select * from t_user u1,(select * from t_user u2) u3

-- UNION和UNION Result
explain
select * from t_user u1
UNION
select * from t_user u2

7.4.3 table(當前表名)

顯示一行的資料時,關於到的表

7.4.5 type(當前表內訪問方式)

查詢的型別最好到最差的依次為:system > const > eq_ref > ref > index > All,一般情況下,得至少保證達到index級別的,最好是能達到ref級別,最高能達到const,system基本上是不能達到

  • system:表中有一行記錄,這是const型別的特例,平時不會出現

  • const:表示通過索引一次就能找到了,const即常量,它用於比較primary key(主鍵)或者unique(唯一索引),因為只匹配一行資料,所以效率快,如果將主鍵置於where條件中,mysql就能將該查詢轉換成為一個常量

  • eq_ref:唯一性索引掃描,對於每個索引鍵,表中只能有一條記錄與之匹配,常用於主鍵或唯一索引掃描

  • ref:非唯一性索引掃描,使用的是普通索引,返回匹配某個單獨值的行,他可能會找到多個符合條件的行,所以他應該屬於查詢或掃描混合體

  • range:只檢索給定範圍的行,使用一個索引來選擇行,如where語句中出現了between,<,>,in等查詢,這種範圍掃描索引比全表掃描要好,因為他只需要開始於索引的某一點,而結束於另一點,不用掃描全部索引。

  • index:掃描所有的索引,這通常比All快,因為索引檔案通常比資料檔案小,index是從索引中讀取,All是從硬碟中讀取資料

  • All:全表掃描,是最差的一種查詢型別

-- const:主鍵索引掃描
explain
select empno from emp where empno = 7369;

-- eq_ref:唯一索引掃描(需要刪除主鍵索引後才能看到效果)
alter table emp  add UNIQUE(ename); -- 新增唯一索引
explain
select ename,sal from emp where ename = 'ALLEN';

-- ref:非唯一索引掃描
alter table emp  add index job_index(job); -- 新增普通索引
explain
select * from emp where job = 'SALESMAN';

-- range:範圍掃描
explain
select ename from emp where ename like 'al%' -- 前面加%會導致索引失效

-- index: 掃描所有索引
explain
select empno from emp 

-- all:全表掃描
explain
select * from emp

7.4.6 possible_keys(可能使用到的索引)

顯示可能應用在這張表中的索引,一個或多個,查詢到的索引不一定是真正用到的索引

7.4.7 key(實際使用到的索引)

實際使用到的索引,如果為null,則表示沒有使用索引,因此會出現possible_keys列可能有期望使用的索引,但是key為null,表示實際沒有使用索引

7.4.8 key-length(使用到的索引長度)

表示索引中使用的位元組數,而通過該列計算查詢中使用的索引長度,在不損失精確性的情況下,長度越短越好,key_len表示的值為索引欄位的可能長度

7.4.9 ref(引用到的上一個表的列)

顯示索引的哪一列被使用了,如果可能的話是一個常數,哪些列或常量被用於查詢索引所使用的欄位

explain
select * from emp e,dept d where e.deptno = d.deptno

7.4.10 rows

根據表統計資訊及索引選用情況,大致估算出找到所需的記錄所需要讀取的行數

7.4.11 Extra(額外資訊說明)

  • Using filesort:說明mysql會對資料使用一個外部的索引排序,而不是按照表內的索引順序進行讀取,mysql中無法利用索引完成的排序操作稱為“檔案排序”

  • Using temporary:使用了臨時表儲存中間結果,mysql在對查詢結果排序時使用臨時表,常見於order by 和分組查詢group by

  • Using index:表示相應的select操作中使用了覆蓋索引(Covering index),避免了訪問表的資料行,效率不錯。如果同時出現Using where,表名索引被用來執行索引鍵值的查詢;如果沒有同時出現Using where,表明索引用來讀取資料而非執行查詢動作。 其中的覆蓋索引含義是所查詢的列是和建立的索引欄位和個數是一一對應的

  • Using where:表明使用了where過濾

  • Using join buffer:表明使用了連線快取,如在查詢的時候會有多次join,則可能會產生臨時表

  • impossible where:表示where子句的值總是false,不能用來獲取任何元祖。

  • select tables optimized away
    在沒有GROUPBY子句的情況下,基於索引優化MIN/MAX操作或者對於MyISAM儲存引擎優化COUNT(*)操作,不必等到執行階段再進行計算,查詢執行計劃生成的階段即完成優化。

  • distinct:優化distinct操作,在找到第一匹配的元組後即停止找同樣值的動作,即一旦MySQL找到了與行相聯合匹配的行,就不再搜尋了。

  • null:代表的沒有使用索引,掃描的是全表。

-- Using index
explain
select empno from emp order by empno

-- Using filesort
explain
select * from emp order by sal

-- Using temporary;
explain
select comm from emp group by comm;

-- Using where
explain
select job from emp where job like 'a%'
小結

type:訪問型別,檢視SQL到底是以何種型別訪問資料的。
key:使用的索引,MySQL用了哪個索引,有時候MySQL用的索引不是最好的,需要force index()。
rows:最大掃描的列數。
extra:重要的額外資訊,特別注意損耗效能的兩個情況,using filesort和using temporary。

八、常見Mysql優化的手段

8.1 硬體層面

1.可以使用更大的記憶體,減少磁碟的IO

2.可以採用多核CPU,可以提高MySQL的執行速度

3.可以採用更好的磁碟來加快IO讀寫速度,如使用固態硬碟

8.2 軟體層面

1.使用合適的儲存引擎,當查詢多的時候可以使用MyISAM儲存引擎,當寫多的時候可以使用InnoDB

8.3 建表

1.資料型別越小越好

​ 通常情況下,應該選擇可以正確儲存資料的最小資料型別,因為他們佔用更小的磁碟、記憶體和CPU快取,但是要確保沒有低估需要儲存值的範圍,在Mysql中的多個地方增加資料類型範圍是一件很痛苦的事情

2.使用簡單的資料型別

​ 簡單的資料型別的操作通常需要消耗更小的CPU資源,比如整型比字串操作的代價更低

​ 如:Mysql中建立時間型別使用data型別或者time型別,而不使用varchar型別

3.儘量避免NULL

​ 通常情況下最好執行列為NOT NULL,除非真的需要儲存NULL值。如果查詢總包含可能為NULL的列,對MySQL來說更難優化,因為可為NULL的列使的索引、索引統計等都變的更加複雜。通常把欄位設定為NOT NULL帶來的效能提升比較小,但是如果計劃在列上建立索引,就應該儘量避免設計成可為NULL的列

8.4 SQL的查詢優化

一些高階的查詢語句

show status;
show global status like "Com_select"; // 查詢所有的
show status like 'Com_select';//執行select操作的次數,一次會話
show status like 'Com_insert';//執行insert操作的次數,注意,對於批量插入的操作,只算一次
show status like 'Com_update';
show status like 'Com_delete';

show status like 'Innodb_rows_read' ;//select查詢返回的行數
show status like 'Innodb_rows_inserted' ;//執行insert操作插入的行數
show status like 'Innodb_rows_updated' ;//執行update操作更新的行數
show status like 'Innodb_rows_deleted' ;//執行delete操作刪除的行數

SQL的機器讀取順序

分析:

從這個順序中我們不難發現,所有的 查詢語句都是從from開始執行的,
在執行過程中,每個步驟都會為下一個步驟生成一個虛擬表,這個虛擬表將作為下一個執行步驟的輸入。

1)首先對from子句中的前兩個表執行一個笛卡爾乘積,此時生成虛擬表 vt1(選擇相對小的表做基礎表)

2)接下來便是應用on篩選器,on 中的邏輯表示式將應用到 vt1 中的各個行,篩選出滿足on邏輯表示式的行,生成虛擬表 vt2

3)如果是left outer join 就把左表在第二步中過濾的新增進來,如果是right outer join 那麼就將右表在第二步中過濾掉的行新增進來,這樣生成虛擬表 vt3

4)如果 from 子句中的表數目多餘兩個表,那麼就將vt3和第三個表連線從而計算笛卡爾乘積,生成虛擬表,該過程就是一個重複1-3的步驟,最終得到一個新的虛擬表 vt3

5)應用where篩選器,對上一步生產的虛擬表引用where篩選器,生成虛擬表vt4

6)group by 子句將中的唯一的值組合成為一組,得到虛擬表vt5。注意:如果應用了group by,那麼後面的所有步驟都只能得到的vt5的列或者是聚合函式(count、sum、avg等)

7)應用having篩選器,生成vt6。having篩選器是第一個也是為唯一一個應用到已分組資料的篩選器。

8)處理select子句。將vt6中的在select中出現的列篩選出來。生成vt7。

9)應用distinct子句,vt7中移除相同的行,生成vt8。事實上如果應用了group by子句那麼distinct是多餘的,

10)應用order by子句。按照order_by_condition排序vt8,此時返回的一個遊標,而不是虛擬表。

11)應用limit子句,對結果集分頁,生成虛擬表vt9

12)返回結果

8.4.1MySQL的慢查詢日誌
8.4.1 .1慢查詢日誌概念

MySQL的慢查詢日誌是MySQL提供的一種日誌記錄,它用來記錄在MySQL中響應時間超過閾值的語句,具體指執行時間超過long_query_time值的SQL,則會被記錄到慢查詢日誌中。long_query_time的預設值為10,意思是執行10S以上的語句。預設情況下,Mysql資料庫並不啟動慢查詢日誌,需要我們手動來設定這個引數,當然,如果不是調優需要的話,一般不建議啟動該引數,因為開啟慢查詢日誌會或多或少帶來一定的效能影響。慢查詢日誌支援將日誌記錄寫入檔案,也支援將日誌記錄寫入資料庫表。

8.4.1.2 慢查詢日誌的查詢和開啟

檢視慢查詢日誌:
select @@slow_query_log;

開啟:
SET GLOBAL slow_query_log=1;

8.4.1.3 查詢慢查詢次數
show status like 'slow_queries';
8.4.1.4 設定查詢的閾值

檢視閾值:
show variables like 'long%'

設定閾值:
set long_query_time=0.0001;

8.4.2 使用執行計劃

採用執行計劃

8.4.3 使用合適的索引

使用合適的索引

是指索引列不能是表示式的一部分,也不能是函式的引數。
應該養成簡化where條件的習慣,始終將索引列單獨放在運算子的一側。

例如:
select * from ... where id + 1 = 5;
這是一個錯誤的用法,mysql無法解析id + 1 = 5 這個方程式,故不會使用到id列上的索引。>

8.4.3.1 使用前置索引

字首索引是選擇字元列的前n個字元作為索引,這樣可以減少索引空間大小,降低重複的索引值,從而提高索引效率。
注意:MySQL無法使用字首索引做ORDER BY 和GROUP BY

8.5 其他的操作優化

8.5.1 插入優化
-- 如
insert into t_table values(1,'zs','gg'),(2,'ls','gg');
8.5.2 刪除優化

如果是刪除一個百萬級的資料表,那麼建議可以先刪除索引,刪除完資料之後,再重新建立索引

8.5.3 表連線查詢

MySQL採用的是驅動表的方式,所以如果是表關聯查詢,建議將小表作為主表,就是以小表來驅動大表

能用between的地方,就不要用in

8.6 庫表結構優化

使用中介軟體Mycat進行讀寫分離等

使用分庫分表