1. 程式人生 > >史上最全mysql刪庫跑路必會姿勢

史上最全mysql刪庫跑路必會姿勢

基礎篇:MySql架構與儲存引擎

邏輯架構圖:

 

 

 

 連線層:

 

mysql啟動後(可以把mysql類比為一個後臺的伺服器),等待客戶端請求,當請求到來後,mysql建立一個一個執行緒處理(執行緒池則分配一個空執行緒,當然也可使用nio執行緒模型。),每個執行緒獨立,擁有獨自記憶體空間。當請求為select請求則沒有關係,但是請求為update時,多執行緒同時修改一塊記憶體,就會引發一系列問題,由此引出 “鎖“的概念。

檢視mysql當前連線數:

show VARIABLES like '%max_connections%'

修改mysql連線數為200
set GLOBAL max_connections = 200

 

同時當客戶端連線到mysql伺服器時,伺服器會對其進行許可權驗證,包括,ip,使用者名稱,密碼的驗證,同時還要驗證是否有對操作某一個庫,表的許可權。

 

SQL處理層:

 

 

show variables like '%query_cache_type%'

SET GLOBAL query_cache_size = 188888888;   

是否開啟mysql查詢結果快取,預設關閉,開啟後,mysql會對查詢出來的結果進行快取,實際應用中業務資料一般不在db層快取

mysql預設開啟sql解析快取;平時我們說的sql快取,一般指的sql解析快取。

解析查詢:

 

 

mysql對客戶端傳入的sql語句會按照一定的規則進行sql解析,而後進行sql優化,最後執行優化過的sql語句。而不是直接執行。

儲存引擎:

show engines;檢視儲存引擎

 

MyISAM

 

進入show VARIABLES like 'datadir'  檢視mysql資料檔案所在路徑,發現myisam引擎會生產三個資料檔案,xxx.frm儲存表結構檔案,所有引擎都有此檔案,xxx.MYD儲存表資料檔案,xxx.MYI儲存表索引檔案

特性:

併發性

支援表級鎖,

支援全文檢索,

支援資料檔案壓縮

試用場景:

只讀類應用;

非事物行應用(資料倉庫,報表,資料)

空間類應用(座標)

 Innodb

 

show VARIABLES like 'innodb_file_per_table' 檢視innodb表空間型別
set global innodb_file_per_table=off      設定innodb使用系統表空間

mysql5.6以前預設使用系統表空間

系統表空間無法簡單的收縮檔案大小。

獨立表空可以通過optimize table 收縮系統檔案

系統表空間會產生io瓶頸

獨立表空間可以同時向多個檔案重新整理資料

推薦使用獨立表空間

特性:

Innodb是一種事務性儲存引擎

完全支援事物的acid特性

redo Log和Undo Log

Innodb支援行級鎖(併發度更高)

試用場景

適合大多數的oltp應用。

 

 

 csv

 

 

 特點:

    以csv格式進行資料儲存,

    所有列都不能為空,

    不支援索引,

    可以直接對資料檔案直接編輯(直接修改文字檔案,達到修改表的目的)。

create table mycsv(id int not null,c1 VARCHAR(10) not null,c2 char(10) not null)
engine=csv;
insert into mycsv values(1,'aaa','bbb'),(2,'cccc','dddd');
修改文字資料
flush TABLES;
select * from mycsv
create index idx_id on mycsv(id)

應用場景:

需要頻繁匯入匯出表資料的場景,如財務報表類

 

Archive

 

 

應用場景:日誌以及資料採集。

 

 Memory

 

show VARIABLES like 'max_heap_table_size' 檢視memory引擎最大空間。

 

 

使用場景:

hash索引用於查詢或者是對映表(郵編和地區對應)

用於儲存資料分析中產生的中間表

用於快取週期性聚合資料的結果表

memory資料容易丟失,所以要求資料可再生。

 

Ferderted

特點:提供了遠端訪問mysql伺服器上表的方法

           本地不儲存資料,資料全部放到遠端伺服器上

           本地需要儲存表結構和遠端伺服器的連線資訊

使用場景:邊界資料庫,表 同步

該引擎預設禁止,啟用時需增加federated引數

 

 

表明,列名需要與遠端表相同

CREATE TABLE `local_fed` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`c1` varchar(10) NOT NULL DEFAULT '',
`c2` char(10) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=federated CONNECTION
='mysql://root:[email protected]:3306/remote/remote_fed'

應用篇:鎖,事物,索引   

 

MyISAM表級鎖的兩種模式:table read lock 表共享讀鎖;table write Lock 表獨佔寫鎖;

 

 

加共享表級讀鎖: lock table 表名 read

1. lock table testmysam READ

啟動另外一個session select * from
testmysam 可以查詢
2. insert into testmysam value(2);
update testmysam set id=2 where id=1;
報錯
3.在另外一個session中
insert into testmysam value(2); 等待
4.在同一個session中
insert into testdemo value(2,'2','3'); 報錯
select * from testdemo ; 報錯
5.在另外一個session中
insert into testdemo value(2,'2','3'); 成功
6.加鎖在同一個session 中 select s.* from testmysam s 報錯
lock table 表名 as 別名 read;
檢視 show status LIKE 'table_locks_waited' 表被鎖過幾次

 

 加獨佔表級寫鎖:lock table 表名 write

1.lock table testmysam WRITE
在同一個session中
insert testmysam value(3);
delete from testmysam where id = 3
select * from testmysam
2.對不同的表操作(報錯)
select s.* from testmysam s
insert into testdemo value(2,'2','3');
3.在其他session中 (等待)
select * from testmysam

 

Innodb行鎖

 共享行鎖又稱讀鎖;當一個事務對某幾行上讀鎖時,允許其他事務對這幾行讀操作,但是不予許其進行寫操作,也不予許其他事務給這幾行上排它鎖,但允許上讀鎖。

排它鎖又稱寫鎖;當一個事務對某幾行上寫鎖時,允許其他事務對這幾行讀操作,不予許其進行寫操作,更不予許其他事務給這幾行上鎖,包括讀鎖。

注意:1.兩個事務不能鎖同一個索引。

           2.insert,delete,update在事務中會預設加上排它鎖

           3.行鎖必須有索引才能實現,否則會自動寫全表,那麼就不是行鎖了

1.
BEGIN
select * from testdemo where id =1 for update
在另外一個session中
update testdemo set c1 = '1' where id = 2 成功
update testdemo set c1 = '1' where id = 1 等待
2.BEGIN
update testdemo set c1 = '1' where id = 1
在另外一個session中
update testdemo set c1 = '1' where id = 1 等待
3.
BEGIN
update testdemo set c1 = '1' where c1 = '1'
在另外一個session中
update testdemo set c1 = '2' where c1 = '2' 等待

 

為什麼需要事務

現在的很多軟體都是多使用者,多程式,多執行緒的,對同一個表可能同時有很多人在用,為保持資料的一致性,所以提出了事務的概念。

 

事務的特性

事務應該具有4個屬性:原子性、一致性、隔離性、永續性。這四個屬性通常稱為ACID特性。

原子性(atomicity)。一個事務是一個不可分割的工作單位,事務中包括的諸操作要麼都做,要麼都不做。

一致性(consistency)。事務必須是使資料庫從一個一致性狀態變到另一個一致性狀態。一致性與原子性是密切相關的。

隔離性(isolation)。一個事務的執行不能被其他事務干擾。即一個事務內部的操作及使用的資料對併發的其他事務是隔離的,併發執行的各個事務之間不能互相干擾。

永續性(durability)。永續性也稱永久性(permanence),指一個事務一旦提交,它對資料庫中資料的改變就應該是永久性的。接下來的其他操作或故障不應該對其有任何影響。

 

事務隔離級別

mysql預設的事務隔離級別為repeatable-read

show variables like '%tx_isolation%';

 

 

未提交讀(READ UNCOMMITED解決的障礙:無; 引入的問題:髒讀

 

set SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

 

測試:

 

啟動兩個session

 

一個session

 

  start TRANSACTION

 

  update account set balance = balance -50 where id = 1

 

另外一個session中查詢

 

select * from account

 

回到第一個session中 回滾事務

 

ROLLBACK

 

在第二個session

 

update account set balance = balance -50 where id = 1

 

查詢結果還是 400

 

第二個session以為結果是350,但前面的400資料為髒讀資料,導致最後的結果和意料中的結果並不一致。

 

已提交讀 READ COMMITED) 解決的障礙:髒讀; 引入的問題:不可重複讀

測試

show variables like '%tx_isolation%';

set SESSION TRANSACTION ISOLATION LEVEL read committed;

一個session

  start TRANSACTION

  update account set balance = balance -50 where id = 1

另外一個session中查詢 (資料並沒改變)

select * from account

回到第一個session中 回滾事務

commit

在第二個session

select * from account (資料已經改變)

 

可重複讀(REPEATABLE READ解決的障礙:不可重複讀; 引入的問題:幻讀

 

測試

show variables like '%tx_isolation%';

set SESSION TRANSACTION ISOLATION LEVEL repeatable read;

一個session

  start TRANSACTION

  update account set balance = balance -50 where id = 1

另外一個session中查詢 (資料並沒改變)

select * from account

回到第一個session中 回滾事務

commit

在第二個session

select * from account (資料並未改變)

可序列化(SERIALIZABLE解決的障礙:可重複讀; 引入的問題:鎖全表,效能低下

測試

show variables like '%tx_isolation%';

set SESSION TRANSACTION ISOLATION LEVEL repeatable read;

account 表有3條記錄,業務規定,最多允許4條記錄。

開啟一個事務

begin

select * from account  發現3條記錄 

開啟另外一個事務

begin

select * from account  發現3條記錄 也是3條記錄

insert into account VALUES(4,'deer',500)

查詢  4條記錄

select * from account

 回到第一個session

insert into account VALUES(5,'james',500)

select * from account  4條記錄

session1 session2 都提交事務 

set SESSION TRANSACTION ISOLATION LEVEL serializable; 重新上面的測試發現插入報錯

 

總結:

事務隔離級別為可重複讀時,如果有索引(包括主鍵索引)的時候,以索引列為條件更新資料,會存在間隙鎖間、行鎖、頁鎖的問題,從而鎖住一些行;如果沒有索引,更新資料時會鎖住整張表

事務隔離級別為序列化時,讀寫資料都會鎖住整張表

 隔離級別越高,越能保證資料的完整性和一致性,但是對併發效能的影響也越大,對於多數應用程式,可以優先考慮把資料庫系統的隔離級別設為Read Committed,它能夠避免髒讀取,而且具有較好的併發效能。

 

 

索引是什麼

MySQL官方對索引的定義為:索引(Index)是幫助MySQL高效獲取資料的資料結構。

可以得到索引的本質:索引是資料結構

平時我們到圖書館,首先看到的都是目錄,通過目錄去查詢想要的書籍會非常的迅速。

 

我們要去圖書館找一本書,這圖書館的書肯定不是線性存放的,它對不同的書籍內容進行了分類存放,整索引由於一個個節點組成,根節點有中間節點,中間節點下面又由子節點,最後一層是葉子節點,

可見,整個索引結構是一棵倒掛著的樹,其實它就是一種資料結構,這種資料結構比前面講到的線性目錄更好的增加了查詢的速度。

 

MySql中的索引其實也是這麼一回事,我們可以在資料庫中建立一系列的索引,比如建立主鍵的時候預設會建立主鍵索引,上圖是一種BTREE的索引。每一個節點都是主鍵的Id

當我們通過ID來查詢內容的時候,首先去查索引庫,在到索引庫後能快速的定位索引的具體位置。

 

索引得分類

 

普通索引:即一個索引只包含單個列,一個表可以有多個單列索引

 

唯一索引:索引列的值必須唯一,但允許有空值

 

複合索引:即一個索引包含多個列

 

聚簇索引(聚集索引):並不是一種單獨的索引型別,而是一種資料儲存方式(索引與資料放在同一個檔案裡)。具體細節取決於不同的實現,InnoDB的聚簇索引其實就是在同一個結構中儲存了B-Tree索引(技術上來說是B+Tree)和資料行。

 

非聚簇索引:不是聚簇索引,就是非聚簇索引

檢視索引

SHOW INDEX FROM table_name\G

建立索引

CREATE  [UNIQUE ] INDEX indexName ON mytable(columnname(length));

ALTER TABLE 表名 ADD  [UNIQUE ]  INDEX [indexName] ON (columnname(length))

刪除索引

DROP INDEX [indexName] ON mytable;

 

優化篇:慢查詢 ,執行計劃,sql優化

  什麼是慢查詢

慢查詢日誌,顧名思義,就是查詢慢的日誌,是指mysql記錄所有執行超過long_query_time引數設定的時間閾值的SQL語句的日誌。該日誌能為SQL語句的優化帶來很好的幫助。預設情況下,慢查詢日誌是關閉的,要使用慢查詢日誌功能,首先要開啟慢查詢日誌功能。

 慢查詢基本配置

 slow_query_log 啟動停止技術慢查詢日誌

 slow_query_log_file 指定慢查詢日誌得儲存路徑及檔案(預設和資料檔案放一起)

 long_query_time 指定記錄慢查詢日誌SQL執行時間得伐值(單位:秒,預設10秒)

 log_queries_not_using_indexes  是否記錄未使用索引的SQL

 log_output 日誌存放的地方【TABLE】【FILE】【FILE,TABLE】

配置了慢查詢後,它會記錄符合條件的SQL

包括:

 查詢語句

資料修改語句

已經回滾得SQL

實操:

通過下面命令檢視下上面的配置:

show VARIABLES like '%slow_query_log%'

show VARIABLES like '%slow_query_log_file%'

show VARIABLES like '%long_query_time%'

show VARIABLES like '%log_queries_not_using_indexes%'

show VARIABLES like 'log_output'

set global long_query_time=0;   ---預設10秒,這裡為了演示方便設定為0

set GLOBAL  slow_query_log = 1; --開啟慢查詢日誌

set global log_output='FILE,TABLE'  --專案開發中日誌只能記錄在日誌檔案中,不能記表中

設定完成後,查詢一些列表可以發現慢查詢的日誌檔案裡面有資料了。

 

 慢查詢解讀

從慢查詢日誌裡面摘選一條慢查詢日誌,資料組成如下

 

第一行:使用者名稱 、使用者的IP資訊、執行緒ID號

第二行:執行花費的時間【單位:毫秒】

第三行:執行獲得鎖的時間

第四行:獲得的結果行數

第五行:掃描的資料行數

第六行:這SQL執行的具體時間

第七行:具體的SQL語句

 

 

執行計劃

  使用EXPLAIN關鍵字可以模擬優化器執行SQL查詢語句,從而知道MySQL是如何處理你的SQL語句的。分析你的查詢語句或是表結構的效能瓶頸。

 執行計劃作用

 表的讀取順序

 資料讀取操作的操作型別

 哪些索引可以使用

 哪些索引被實際使用

 表之間的引用

 每張表有多少行被優化器查詢

 

執行計劃的語法

執行計劃的語法其實非常簡單: 在SQL查詢的前面加上EXPLAIN關鍵字就行。

比如:EXPLAIN select * from table1

重點的就是EXPLAIN後面你要分析的SQL語句 

 

 

ID列

ID列:描述select查詢的序列號,包含一組數字,表示查詢中執行select子句或操作表的順序

根據ID的數值結果可以分成一下三種情況

 id相同:執行順序由上至下

 id不同:如果是子查詢,id的序號會遞增,id值越大優先順序越高,越先被執行

 id相同不同:同時存在

分別舉例來看

 

如上圖所示,ID列的值全為1,代表執行的允許從t1開始載入,依次為t3與t2

 

EXPLAIN

select t2.* from t1,t2,t3  where t1.id = t2.id and t1.id = t3.id

and t1.other_column = '';

Id不同

 

如果是子查詢,id的序號會遞增,id值越大優先順序越高,越先被執行

EXPLAIN

select t2.* from  t2 where id = (

select id from t1 where id =  (select t3.id from t3 where t3.other_column='')

);

 Id相同又不同

 

id如果相同,可以認為是一組,從上往下順序執行;

在所有組中,id值越大,優先順序越高,越先執行

EXPLAIN

select t2.* from (

 select t3.id

from t3 where t3.other_column = ''

) s1 ,t2 where s1.id = t2.id

 select_type列

Select_type:查詢的型別,

要是用於區別:普通查詢、聯合查詢、子查詢等的複雜查詢

型別如下

 

  SIMPLE

EXPLAIN select * from t1

簡單的 select 查詢,查詢中不包含子查詢或者UNION

 

PRIMARY與SUBQUERY

PRIMARY:查詢中若包含任何複雜的子部分,最外層查詢則被標記為

SUBQUERY:在SELECT或WHERE列表中包含了子查詢

EXPLAIN

select t1.*,(select t2.id from t2 where t2.id = 1 ) from t1 

 

 

 DERIVED

在FROM列表中包含的子查詢被標記為DERIVED(衍生)

MySQL會遞迴執行這些子查詢, 把結果放在臨時表裡。

 

.UNION RESULT 與UNION

UNION:若第二個SELECT出現在UNION之後,則被標記為UNION;

UNION RESULT:從UNION表獲取結果的SELECT

#UNION RESULT ,UNION

EXPLAIN

select * from t1

UNION

select * from t2

 

 table列

顯示這一行的資料是關於哪張表的

 

Type列

type顯示的是訪問型別,是較為重要的一個指標,結果值從最好到最壞依次是:

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

需要記憶的

system>const>eq_ref>ref>range>index>ALL

一般來說,得保證查詢至少達到range級別,最好能達到ref。

 System與const

System:表只有一行記錄(等於系統表),這是const型別的特列,平時不會出現,這個也可以忽略不計

Const:表示通過索引一次就找到了

const用於比較primary key或者unique索引。因為只匹配一行資料,所以很快

如將主鍵置於where列表中,MySQL就能將該查詢轉換為一個常量

 

  eq_ref

 唯一性索引掃描,對於每個索引鍵,表中只有一條記錄與之匹配。常見於主鍵或唯一索引掃描

 

 Ref

 非唯一性索引掃描,返回匹配某個單獨值的所有行.

本質上也是一種索引訪問,它返回所有匹配某個單獨值的行,然而,它可能會找到多個符合條件的行,所以他應該屬於查詢和掃描的混合體

 

 Range

只檢索給定範圍的行,使用一個索引來選擇行。key 列顯示使用了哪個索引

一般就是在你的where語句中出現了between、<、>、in等的查詢

這種範圍掃描索引掃描比全表掃描要好,因為它只需要開始於索引的某一點,而結束語另一點,不用掃描全部索引。

 

 

Index

當查詢的結果全為索引列的時候,雖然也是全部掃描,但是隻查詢的索引庫,而沒有去查詢

資料。

 

All

Full Table Scan,將遍歷全表以找到匹配的行

 

 

possible_keys 與Key 

possible_keys:可能使用的key

Key:實際使用的索引。如果為NULL,則沒有使用索引

查詢中若使用了覆蓋索引,則該索引和查詢的select欄位重疊

 

 key_len

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

key_len顯示的值為索引欄位的最大可能長度,並非實際使用長度,即key_len是根據表定義計算而得,不是通過表內檢索出的

 

 

 key_len表示索引使用的位元組數,

 根據這個值,就可以判斷索引使用情況,特別是在組合索引的時候,判斷所有的索引欄位是否都被查詢用到。

 char和varchar跟字元編碼也有密切的聯絡,

 latin1佔用1個位元組,gbk佔用2個位元組,utf8佔用3個位元組。(不同字元編碼佔用的儲存空間不同)

 

 

字元型別

 

字元型別-索引欄位為char型別+不可為Null時

 

name這一列為char(10),字符集為utf-8佔用3個位元組Keylen=10*3

字元型別-索引欄位為char型別+允許為Null時

 

name這一列為char(10),字符集為utf-8佔用3個位元組,外加需要存入一個null值

Keylen=10*3+1(null) 結果為31

索引欄位為varchar型別+不可為Null時

 

Keylen=varchar(n)變長欄位+不允許Null=n*(utf8=3,gbk=2,latin1=1)+2

 索引欄位為varchar型別+允許為Null時

 

Keylen=varchar(n)變長欄位+允許Null=n*(utf8=3,gbk=2,latin1=1)+1(NULL)+2

 

總結

字元型別

變長欄位需要額外的2個位元組(VARCHAR值儲存時只儲存需要的字元數,另加一個位元組來記錄長度(如果列宣告的長度超過255,則使用兩個位元組),所以VARCAHR索引長度計算時候要加2),固定長度欄位不需要額外的位元組。

而NULL都需要1個位元組的額外空間,所以索引欄位最好不要為NULL,因為NULL讓統計更加複雜並且需要額外的儲存空間。

複合索引有最左字首的特性,如果複合索引能全部使用上,則是複合索引欄位的索引長度之和,這也可以用來判定複合索引是否部分使用,還是全部使用。

整數/浮點數/時間型別的索引長度

NOT NULL=欄位本身的欄位長度

        NULL=欄位本身的欄位長度+1(因為需要有是否為空的標記,這個標記需要佔用1個位元組)

datetime型別在5.6中欄位長度是5個位元組,datetime型別在5.5中欄位長度是8個位元組

 

 Ref

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

 

由key_len可知t1表的idx_col1_col2被充分使用,col1匹配t2表的col1,col2匹配了一個常量,即 'ac'

其中 【shared.t2.col1】 為 【資料庫.表.列】

Rows

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

 

Extra

包含不適合在其他列中顯示但十分重要的額外資訊。

 

 Using filesort

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

當發現有Using filesort 後,實際上就是發現了可以優化的地方

 

上圖其實是一種索引失效的情況,後面會講,可以看出查詢中用到了個聯合索引,索引分別為col1,col2,col3

 

當我排序新增了個col2,發現using filesort 就沒有了。

 

Using temporary

 

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

 

 

尤其發現在執行計劃裡面有using filesort而且還有Using temporary的時候,特別需要注意

Using index

表示相應的select操作中使用了覆蓋索引(Covering Index),避免訪問了表的資料行,效率不錯!

如果同時出現using where,表明索引被用來執行索引鍵值的查詢;

 

如果沒有同時出現using where,表明索引用來讀取資料而非執行查詢動作

 

 

 覆蓋索引:

覆蓋索引(Covering Index),一說為索引覆蓋。

理解方式一:就是select的資料列只用從索引中就能夠取得,不必讀取資料行,MySQL可以利用索引返回select列表中的欄位,而不必根據索引再次讀取資料檔案,換句話說查詢列要被所建的索引覆蓋。

理解方式二:索引是高效找到行的一個方法,但是一般資料庫也能使用索引找到一個列的資料,因此它不必讀取整個行。畢竟索引葉子節點儲存了它們索引的資料;當能通過讀取索引就可以得到想要的資料,那就不需要讀取行了。一個索引包含了(或覆蓋了)滿足查詢結果的資料就叫做覆蓋索引

注意:

如果要使用覆蓋索引,一定要注意select列表中只取出需要的列,不可select *,

因為如果將所有欄位一起做索引會導致索引檔案過大,查詢效能下降。

所以,千萬不能為了查詢而在所有列上都建立索引,會嚴重影響修改維護的效能。

 

Using where 與 using join buffer

Using where

表明使用了where過濾

using join buffer

使用了連線快取:

 

 impossible where

where子句的值總是false,不能用來獲取任何元組

 

 

 

sql優化順口溜

 全職匹配我最愛,最左字首要遵守;

 帶頭大哥不能死,中間兄弟不能斷;

 索引列上少計算,範圍之後全失效;

 LIKE百分寫最右,覆蓋索引不寫*;

 

 全職匹配我最愛?

 

當建立了索引列後,能在where條件中使用索引的儘量所用。

 

最左字首要遵守,帶頭大哥不能死,中間兄弟不能斷?

 

如果索引了多列,要遵守最左字首法則。指的是查詢從索引的最左前列開始並且不跳過索引中的列。

聯合索引index(name,age,pos),帶頭大哥name,少了索引直接失效,使用(name,pos)丟下中間兄弟age索引失效。

 

索引列上少計算?

 

不在索引列上做任何操作(計算、函式、(自動or手動)型別轉換),會導致索引失效而轉向全表掃描

 

 範圍之後全失效?

 

中間有範圍查詢會導致後面的索引列全部失效

EXPLAIN SELECT * FROM staffs WHERE NAME = 'July'  and age >22 and pos='manager'

 

 LIKE百分寫最右?

 

like以萬用字元開頭('%abc...')mysql索引失效會變成全表掃描的操作

解決方式:覆蓋索引

EXPLAIN select name,age,pos from staffs where name like '%july%'

 

覆蓋索引不寫* ?

使用select * from  破壞了了覆蓋索引的使用條件。

 

補充兩個比較偏的

Null/Not 有影響

索引不可為空

 

 

在欄位為not null的情況下,使用is null 或 is not null 會導致索引失效

解決方式:覆蓋索引

EXPLAIN select  name,age,pos from staffs where name is not null

 

索引可為空:

 

 

Is not null 的情況會導致索引失效