'MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?'

MySQL SQL 數據庫 程序員的苦咖啡 2019-09-11
"
"
MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

在我們使用MySQL的過程中,隨著數據量越來越大,查詢顯得有些吃力,這時候就要針對查詢就行優化,針對查詢優化,通過給字段添加索引可以提高數據的讀取速度,提高項目的併發能力和抗壓能力。在上一篇我們講了給數據庫中的表添加索引,來提高它的查詢速度,但是會有另外一種情況出現,那就是我們給表中字段加了索引,但是查詢的時候依舊很慢,沒有什麼變化,這時就是因為建立的索引失效了,今天就來講一講索引失效的情況!

"
MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

在我們使用MySQL的過程中,隨著數據量越來越大,查詢顯得有些吃力,這時候就要針對查詢就行優化,針對查詢優化,通過給字段添加索引可以提高數據的讀取速度,提高項目的併發能力和抗壓能力。在上一篇我們講了給數據庫中的表添加索引,來提高它的查詢速度,但是會有另外一種情況出現,那就是我們給表中字段加了索引,但是查詢的時候依舊很慢,沒有什麼變化,這時就是因為建立的索引失效了,今天就來講一講索引失效的情況!

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於查看索引是否失效,MySQL數據庫針對每一條SQL語句,提供了一個查看它的執行計劃的工具,叫做EXPLAIN,咱們先來了解一下這個工具。首先說一下接下來用到的表,創建的表結構為:

CREATE TABLE `tb_user` (
`id` BIGINT (20),
`user_name` VARCHAR (200),
`user_password` VARCHAR (200),
`birth` DATETIME ,
`sex` CHAR (4),
\t\t\t\t `age` int(8),
`email` VARCHAR (200),
`mobile` VARCHAR (200),
`create_date` DATETIME ,
`update_date` DATETIME ,
`description` VARCHAR (800)
) ENGINE=INNODB;

創建一個存儲函數,向裡面插入一百萬條數據:

DELIMITER $$
CREATE
PROCEDURE insert_tb_user()
BEGIN
DECLARE i INT;
SET i=0;
WHILE i>=0 && i<= 1000000 DO
INSERT INTO tb_user
(`id`, `user_name`, `user_password`, `birth`, `sex`, `age`, `email`, `mobile`, `create_date`, `update_date`, `description`) VALUES
(i,concat('admin',i),concat('admin',i),NOW(),'M',i,'[email protected]',concat('12345',i),NOW(),NOW(),concat('超級管理員',i));
SET i=i + 1;
END WHILE;

END$$
DELIMITER ;
-- 執行存儲函數
call insert_tb_user()

生成的表數據如下:

"
MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

在我們使用MySQL的過程中,隨著數據量越來越大,查詢顯得有些吃力,這時候就要針對查詢就行優化,針對查詢優化,通過給字段添加索引可以提高數據的讀取速度,提高項目的併發能力和抗壓能力。在上一篇我們講了給數據庫中的表添加索引,來提高它的查詢速度,但是會有另外一種情況出現,那就是我們給表中字段加了索引,但是查詢的時候依舊很慢,沒有什麼變化,這時就是因為建立的索引失效了,今天就來講一講索引失效的情況!

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於查看索引是否失效,MySQL數據庫針對每一條SQL語句,提供了一個查看它的執行計劃的工具,叫做EXPLAIN,咱們先來了解一下這個工具。首先說一下接下來用到的表,創建的表結構為:

CREATE TABLE `tb_user` (
`id` BIGINT (20),
`user_name` VARCHAR (200),
`user_password` VARCHAR (200),
`birth` DATETIME ,
`sex` CHAR (4),
\t\t\t\t `age` int(8),
`email` VARCHAR (200),
`mobile` VARCHAR (200),
`create_date` DATETIME ,
`update_date` DATETIME ,
`description` VARCHAR (800)
) ENGINE=INNODB;

創建一個存儲函數,向裡面插入一百萬條數據:

DELIMITER $$
CREATE
PROCEDURE insert_tb_user()
BEGIN
DECLARE i INT;
SET i=0;
WHILE i>=0 && i<= 1000000 DO
INSERT INTO tb_user
(`id`, `user_name`, `user_password`, `birth`, `sex`, `age`, `email`, `mobile`, `create_date`, `update_date`, `description`) VALUES
(i,concat('admin',i),concat('admin',i),NOW(),'M',i,'[email protected]',concat('12345',i),NOW(),NOW(),concat('超級管理員',i));
SET i=i + 1;
END WHILE;

END$$
DELIMITER ;
-- 執行存儲函數
call insert_tb_user()

生成的表數據如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

利用這個表,我們來介紹一下執行計劃和索引失效的情況。

首先來看一下執行計劃的結果是什麼樣的,執行計劃的查看,就是在查詢語句的前面加上EXPLAIN關鍵字就可以了:

"
MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

在我們使用MySQL的過程中,隨著數據量越來越大,查詢顯得有些吃力,這時候就要針對查詢就行優化,針對查詢優化,通過給字段添加索引可以提高數據的讀取速度,提高項目的併發能力和抗壓能力。在上一篇我們講了給數據庫中的表添加索引,來提高它的查詢速度,但是會有另外一種情況出現,那就是我們給表中字段加了索引,但是查詢的時候依舊很慢,沒有什麼變化,這時就是因為建立的索引失效了,今天就來講一講索引失效的情況!

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於查看索引是否失效,MySQL數據庫針對每一條SQL語句,提供了一個查看它的執行計劃的工具,叫做EXPLAIN,咱們先來了解一下這個工具。首先說一下接下來用到的表,創建的表結構為:

CREATE TABLE `tb_user` (
`id` BIGINT (20),
`user_name` VARCHAR (200),
`user_password` VARCHAR (200),
`birth` DATETIME ,
`sex` CHAR (4),
\t\t\t\t `age` int(8),
`email` VARCHAR (200),
`mobile` VARCHAR (200),
`create_date` DATETIME ,
`update_date` DATETIME ,
`description` VARCHAR (800)
) ENGINE=INNODB;

創建一個存儲函數,向裡面插入一百萬條數據:

DELIMITER $$
CREATE
PROCEDURE insert_tb_user()
BEGIN
DECLARE i INT;
SET i=0;
WHILE i>=0 && i<= 1000000 DO
INSERT INTO tb_user
(`id`, `user_name`, `user_password`, `birth`, `sex`, `age`, `email`, `mobile`, `create_date`, `update_date`, `description`) VALUES
(i,concat('admin',i),concat('admin',i),NOW(),'M',i,'[email protected]',concat('12345',i),NOW(),NOW(),concat('超級管理員',i));
SET i=i + 1;
END WHILE;

END$$
DELIMITER ;
-- 執行存儲函數
call insert_tb_user()

生成的表數據如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

利用這個表,我們來介紹一下執行計劃和索引失效的情況。

首先來看一下執行計劃的結果是什麼樣的,執行計劃的查看,就是在查詢語句的前面加上EXPLAIN關鍵字就可以了:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於這些字段的意思,咱們一一來解釋:

一、 id,SELECT識別符。

*id相同時,執行順序由上至下

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

二、select_type,查詢中每個select子句的類型

*SIMPLE(簡單SELECT,不使用UNION或子查詢等)

*PRIMARY(子查詢中最外層查詢)

*UNION(UNION中的第二個或後面的SELECT語句)

*DEPENDENT UNION(UNION中的第二個或後面的SELECT語句)

*UNION RESULT(UNION的結果,union語句中第二個select開始後面所有select)

*SUBQUERY(子查詢中的第一個SELECT,結果不依賴於外部查詢)

*DEPENDENT SUBQUERY(子查詢中的第一個SELECT,依賴於外部查詢)

* DERIVED(派生表的SELECT, FROM子句的子查詢)

* UNCACHEABLE SUBQUERY(一個子查詢的結果不能被緩存,必須重新評估外鏈接的第一行)

三、 table,顯示這一步所訪問數據庫中表名稱。

四、type,對錶訪問方式

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

*index: Full Index Scan,index與ALL區別為index類型只遍歷索引樹

*range:只檢索給定範圍的行,使用一個索引來選擇行

*ref: 表示上述表的連接匹配條件,即哪些列或常量被用於查找索引列上的值

*eq_ref: 類似ref,區別就在使用的索引是唯一索引,對於每個索引鍵值,表中只有一條記錄匹配,簡單來說,就是多表連接中使用primary key或者 unique key作為關聯條件

*const、system: 當MySQL對查詢某部分進行優化,並轉換為一個常量時,使用這些類型訪問。如將主鍵置於where列表中,MySQL就能將該查詢轉換為一個常量,system是const類型的特例,當查詢的表只有一行的情況下,使用system

*NULL: MySQL在優化過程中分解語句,執行時甚至不用訪問表或索引,例如從一個索引列裡選取最小值可以通過單獨索引查找完成。

五、 possible_keys,可能使用的索引。

六、key,實際使用的索引

七、key_len,索引中使用的字節數,可通過該列計算查詢中使用的索引的長度

八、ref,列與索引的比較,表示上述表的連接匹配條件

九、rows,估算出結果集行數

十、Extra,MySQL解決查詢的詳細信息

*Using where:不用讀取表中所有信息,僅通過索引就可以獲取所需數據

*Using temporary:表示MySQL需要使用臨時表來存儲結果集,group by ; order by

*Using filesort:包含 order by ,而且無法利用索引完成的排序操作稱為“文件排序”

*Using join buffer:該值強調了在獲取連接條件時沒有使用索引,並且需要連接緩衝區來存儲中間結果。

*Impossible where:這個值強調了where語句會導致沒有符合條件的行。

*Select tables optimized away:這個值意味著僅通過使用索引,優化器可能僅從聚合函數結果中返回一行

*No tables used:Query語句中使用from dual 或不含任何from子句

以上就是對EXPLAIN工具的一個介紹,瞭解了這個工具後,我們結合這個執行工具,來看一看哪些情況會導致這個索引失效!

第一種情況:針對聯合索引,是否遵循最左匹配原則;

我們user_name,user_password,mobile建立一個聯合索引,如下:

"
MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

在我們使用MySQL的過程中,隨著數據量越來越大,查詢顯得有些吃力,這時候就要針對查詢就行優化,針對查詢優化,通過給字段添加索引可以提高數據的讀取速度,提高項目的併發能力和抗壓能力。在上一篇我們講了給數據庫中的表添加索引,來提高它的查詢速度,但是會有另外一種情況出現,那就是我們給表中字段加了索引,但是查詢的時候依舊很慢,沒有什麼變化,這時就是因為建立的索引失效了,今天就來講一講索引失效的情況!

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於查看索引是否失效,MySQL數據庫針對每一條SQL語句,提供了一個查看它的執行計劃的工具,叫做EXPLAIN,咱們先來了解一下這個工具。首先說一下接下來用到的表,創建的表結構為:

CREATE TABLE `tb_user` (
`id` BIGINT (20),
`user_name` VARCHAR (200),
`user_password` VARCHAR (200),
`birth` DATETIME ,
`sex` CHAR (4),
\t\t\t\t `age` int(8),
`email` VARCHAR (200),
`mobile` VARCHAR (200),
`create_date` DATETIME ,
`update_date` DATETIME ,
`description` VARCHAR (800)
) ENGINE=INNODB;

創建一個存儲函數,向裡面插入一百萬條數據:

DELIMITER $$
CREATE
PROCEDURE insert_tb_user()
BEGIN
DECLARE i INT;
SET i=0;
WHILE i>=0 && i<= 1000000 DO
INSERT INTO tb_user
(`id`, `user_name`, `user_password`, `birth`, `sex`, `age`, `email`, `mobile`, `create_date`, `update_date`, `description`) VALUES
(i,concat('admin',i),concat('admin',i),NOW(),'M',i,'[email protected]',concat('12345',i),NOW(),NOW(),concat('超級管理員',i));
SET i=i + 1;
END WHILE;

END$$
DELIMITER ;
-- 執行存儲函數
call insert_tb_user()

生成的表數據如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

利用這個表,我們來介紹一下執行計劃和索引失效的情況。

首先來看一下執行計劃的結果是什麼樣的,執行計劃的查看,就是在查詢語句的前面加上EXPLAIN關鍵字就可以了:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於這些字段的意思,咱們一一來解釋:

一、 id,SELECT識別符。

*id相同時,執行順序由上至下

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

二、select_type,查詢中每個select子句的類型

*SIMPLE(簡單SELECT,不使用UNION或子查詢等)

*PRIMARY(子查詢中最外層查詢)

*UNION(UNION中的第二個或後面的SELECT語句)

*DEPENDENT UNION(UNION中的第二個或後面的SELECT語句)

*UNION RESULT(UNION的結果,union語句中第二個select開始後面所有select)

*SUBQUERY(子查詢中的第一個SELECT,結果不依賴於外部查詢)

*DEPENDENT SUBQUERY(子查詢中的第一個SELECT,依賴於外部查詢)

* DERIVED(派生表的SELECT, FROM子句的子查詢)

* UNCACHEABLE SUBQUERY(一個子查詢的結果不能被緩存,必須重新評估外鏈接的第一行)

三、 table,顯示這一步所訪問數據庫中表名稱。

四、type,對錶訪問方式

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

*index: Full Index Scan,index與ALL區別為index類型只遍歷索引樹

*range:只檢索給定範圍的行,使用一個索引來選擇行

*ref: 表示上述表的連接匹配條件,即哪些列或常量被用於查找索引列上的值

*eq_ref: 類似ref,區別就在使用的索引是唯一索引,對於每個索引鍵值,表中只有一條記錄匹配,簡單來說,就是多表連接中使用primary key或者 unique key作為關聯條件

*const、system: 當MySQL對查詢某部分進行優化,並轉換為一個常量時,使用這些類型訪問。如將主鍵置於where列表中,MySQL就能將該查詢轉換為一個常量,system是const類型的特例,當查詢的表只有一行的情況下,使用system

*NULL: MySQL在優化過程中分解語句,執行時甚至不用訪問表或索引,例如從一個索引列裡選取最小值可以通過單獨索引查找完成。

五、 possible_keys,可能使用的索引。

六、key,實際使用的索引

七、key_len,索引中使用的字節數,可通過該列計算查詢中使用的索引的長度

八、ref,列與索引的比較,表示上述表的連接匹配條件

九、rows,估算出結果集行數

十、Extra,MySQL解決查詢的詳細信息

*Using where:不用讀取表中所有信息,僅通過索引就可以獲取所需數據

*Using temporary:表示MySQL需要使用臨時表來存儲結果集,group by ; order by

*Using filesort:包含 order by ,而且無法利用索引完成的排序操作稱為“文件排序”

*Using join buffer:該值強調了在獲取連接條件時沒有使用索引,並且需要連接緩衝區來存儲中間結果。

*Impossible where:這個值強調了where語句會導致沒有符合條件的行。

*Select tables optimized away:這個值意味著僅通過使用索引,優化器可能僅從聚合函數結果中返回一行

*No tables used:Query語句中使用from dual 或不含任何from子句

以上就是對EXPLAIN工具的一個介紹,瞭解了這個工具後,我們結合這個執行工具,來看一看哪些情況會導致這個索引失效!

第一種情況:針對聯合索引,是否遵循最左匹配原則;

我們user_name,user_password,mobile建立一個聯合索引,如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

聯合索引其實是建立了三個索引,也就是user_name的索引,user_name,user_password的索引,user_name,user_password,mobile的索引,最左匹配原則的意思,是否在語句中使用了最左建立的索引,也就是user_name的索引,演示一下:

"
MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

在我們使用MySQL的過程中,隨著數據量越來越大,查詢顯得有些吃力,這時候就要針對查詢就行優化,針對查詢優化,通過給字段添加索引可以提高數據的讀取速度,提高項目的併發能力和抗壓能力。在上一篇我們講了給數據庫中的表添加索引,來提高它的查詢速度,但是會有另外一種情況出現,那就是我們給表中字段加了索引,但是查詢的時候依舊很慢,沒有什麼變化,這時就是因為建立的索引失效了,今天就來講一講索引失效的情況!

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於查看索引是否失效,MySQL數據庫針對每一條SQL語句,提供了一個查看它的執行計劃的工具,叫做EXPLAIN,咱們先來了解一下這個工具。首先說一下接下來用到的表,創建的表結構為:

CREATE TABLE `tb_user` (
`id` BIGINT (20),
`user_name` VARCHAR (200),
`user_password` VARCHAR (200),
`birth` DATETIME ,
`sex` CHAR (4),
\t\t\t\t `age` int(8),
`email` VARCHAR (200),
`mobile` VARCHAR (200),
`create_date` DATETIME ,
`update_date` DATETIME ,
`description` VARCHAR (800)
) ENGINE=INNODB;

創建一個存儲函數,向裡面插入一百萬條數據:

DELIMITER $$
CREATE
PROCEDURE insert_tb_user()
BEGIN
DECLARE i INT;
SET i=0;
WHILE i>=0 && i<= 1000000 DO
INSERT INTO tb_user
(`id`, `user_name`, `user_password`, `birth`, `sex`, `age`, `email`, `mobile`, `create_date`, `update_date`, `description`) VALUES
(i,concat('admin',i),concat('admin',i),NOW(),'M',i,'[email protected]',concat('12345',i),NOW(),NOW(),concat('超級管理員',i));
SET i=i + 1;
END WHILE;

END$$
DELIMITER ;
-- 執行存儲函數
call insert_tb_user()

生成的表數據如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

利用這個表,我們來介紹一下執行計劃和索引失效的情況。

首先來看一下執行計劃的結果是什麼樣的,執行計劃的查看,就是在查詢語句的前面加上EXPLAIN關鍵字就可以了:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於這些字段的意思,咱們一一來解釋:

一、 id,SELECT識別符。

*id相同時,執行順序由上至下

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

二、select_type,查詢中每個select子句的類型

*SIMPLE(簡單SELECT,不使用UNION或子查詢等)

*PRIMARY(子查詢中最外層查詢)

*UNION(UNION中的第二個或後面的SELECT語句)

*DEPENDENT UNION(UNION中的第二個或後面的SELECT語句)

*UNION RESULT(UNION的結果,union語句中第二個select開始後面所有select)

*SUBQUERY(子查詢中的第一個SELECT,結果不依賴於外部查詢)

*DEPENDENT SUBQUERY(子查詢中的第一個SELECT,依賴於外部查詢)

* DERIVED(派生表的SELECT, FROM子句的子查詢)

* UNCACHEABLE SUBQUERY(一個子查詢的結果不能被緩存,必須重新評估外鏈接的第一行)

三、 table,顯示這一步所訪問數據庫中表名稱。

四、type,對錶訪問方式

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

*index: Full Index Scan,index與ALL區別為index類型只遍歷索引樹

*range:只檢索給定範圍的行,使用一個索引來選擇行

*ref: 表示上述表的連接匹配條件,即哪些列或常量被用於查找索引列上的值

*eq_ref: 類似ref,區別就在使用的索引是唯一索引,對於每個索引鍵值,表中只有一條記錄匹配,簡單來說,就是多表連接中使用primary key或者 unique key作為關聯條件

*const、system: 當MySQL對查詢某部分進行優化,並轉換為一個常量時,使用這些類型訪問。如將主鍵置於where列表中,MySQL就能將該查詢轉換為一個常量,system是const類型的特例,當查詢的表只有一行的情況下,使用system

*NULL: MySQL在優化過程中分解語句,執行時甚至不用訪問表或索引,例如從一個索引列裡選取最小值可以通過單獨索引查找完成。

五、 possible_keys,可能使用的索引。

六、key,實際使用的索引

七、key_len,索引中使用的字節數,可通過該列計算查詢中使用的索引的長度

八、ref,列與索引的比較,表示上述表的連接匹配條件

九、rows,估算出結果集行數

十、Extra,MySQL解決查詢的詳細信息

*Using where:不用讀取表中所有信息,僅通過索引就可以獲取所需數據

*Using temporary:表示MySQL需要使用臨時表來存儲結果集,group by ; order by

*Using filesort:包含 order by ,而且無法利用索引完成的排序操作稱為“文件排序”

*Using join buffer:該值強調了在獲取連接條件時沒有使用索引,並且需要連接緩衝區來存儲中間結果。

*Impossible where:這個值強調了where語句會導致沒有符合條件的行。

*Select tables optimized away:這個值意味著僅通過使用索引,優化器可能僅從聚合函數結果中返回一行

*No tables used:Query語句中使用from dual 或不含任何from子句

以上就是對EXPLAIN工具的一個介紹,瞭解了這個工具後,我們結合這個執行工具,來看一看哪些情況會導致這個索引失效!

第一種情況:針對聯合索引,是否遵循最左匹配原則;

我們user_name,user_password,mobile建立一個聯合索引,如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

聯合索引其實是建立了三個索引,也就是user_name的索引,user_name,user_password的索引,user_name,user_password,mobile的索引,最左匹配原則的意思,是否在語句中使用了最左建立的索引,也就是user_name的索引,演示一下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

當我們把user_name的查詢條件去掉之後,會是什麼情況呢?

"
MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

在我們使用MySQL的過程中,隨著數據量越來越大,查詢顯得有些吃力,這時候就要針對查詢就行優化,針對查詢優化,通過給字段添加索引可以提高數據的讀取速度,提高項目的併發能力和抗壓能力。在上一篇我們講了給數據庫中的表添加索引,來提高它的查詢速度,但是會有另外一種情況出現,那就是我們給表中字段加了索引,但是查詢的時候依舊很慢,沒有什麼變化,這時就是因為建立的索引失效了,今天就來講一講索引失效的情況!

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於查看索引是否失效,MySQL數據庫針對每一條SQL語句,提供了一個查看它的執行計劃的工具,叫做EXPLAIN,咱們先來了解一下這個工具。首先說一下接下來用到的表,創建的表結構為:

CREATE TABLE `tb_user` (
`id` BIGINT (20),
`user_name` VARCHAR (200),
`user_password` VARCHAR (200),
`birth` DATETIME ,
`sex` CHAR (4),
\t\t\t\t `age` int(8),
`email` VARCHAR (200),
`mobile` VARCHAR (200),
`create_date` DATETIME ,
`update_date` DATETIME ,
`description` VARCHAR (800)
) ENGINE=INNODB;

創建一個存儲函數,向裡面插入一百萬條數據:

DELIMITER $$
CREATE
PROCEDURE insert_tb_user()
BEGIN
DECLARE i INT;
SET i=0;
WHILE i>=0 && i<= 1000000 DO
INSERT INTO tb_user
(`id`, `user_name`, `user_password`, `birth`, `sex`, `age`, `email`, `mobile`, `create_date`, `update_date`, `description`) VALUES
(i,concat('admin',i),concat('admin',i),NOW(),'M',i,'[email protected]',concat('12345',i),NOW(),NOW(),concat('超級管理員',i));
SET i=i + 1;
END WHILE;

END$$
DELIMITER ;
-- 執行存儲函數
call insert_tb_user()

生成的表數據如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

利用這個表,我們來介紹一下執行計劃和索引失效的情況。

首先來看一下執行計劃的結果是什麼樣的,執行計劃的查看,就是在查詢語句的前面加上EXPLAIN關鍵字就可以了:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於這些字段的意思,咱們一一來解釋:

一、 id,SELECT識別符。

*id相同時,執行順序由上至下

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

二、select_type,查詢中每個select子句的類型

*SIMPLE(簡單SELECT,不使用UNION或子查詢等)

*PRIMARY(子查詢中最外層查詢)

*UNION(UNION中的第二個或後面的SELECT語句)

*DEPENDENT UNION(UNION中的第二個或後面的SELECT語句)

*UNION RESULT(UNION的結果,union語句中第二個select開始後面所有select)

*SUBQUERY(子查詢中的第一個SELECT,結果不依賴於外部查詢)

*DEPENDENT SUBQUERY(子查詢中的第一個SELECT,依賴於外部查詢)

* DERIVED(派生表的SELECT, FROM子句的子查詢)

* UNCACHEABLE SUBQUERY(一個子查詢的結果不能被緩存,必須重新評估外鏈接的第一行)

三、 table,顯示這一步所訪問數據庫中表名稱。

四、type,對錶訪問方式

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

*index: Full Index Scan,index與ALL區別為index類型只遍歷索引樹

*range:只檢索給定範圍的行,使用一個索引來選擇行

*ref: 表示上述表的連接匹配條件,即哪些列或常量被用於查找索引列上的值

*eq_ref: 類似ref,區別就在使用的索引是唯一索引,對於每個索引鍵值,表中只有一條記錄匹配,簡單來說,就是多表連接中使用primary key或者 unique key作為關聯條件

*const、system: 當MySQL對查詢某部分進行優化,並轉換為一個常量時,使用這些類型訪問。如將主鍵置於where列表中,MySQL就能將該查詢轉換為一個常量,system是const類型的特例,當查詢的表只有一行的情況下,使用system

*NULL: MySQL在優化過程中分解語句,執行時甚至不用訪問表或索引,例如從一個索引列裡選取最小值可以通過單獨索引查找完成。

五、 possible_keys,可能使用的索引。

六、key,實際使用的索引

七、key_len,索引中使用的字節數,可通過該列計算查詢中使用的索引的長度

八、ref,列與索引的比較,表示上述表的連接匹配條件

九、rows,估算出結果集行數

十、Extra,MySQL解決查詢的詳細信息

*Using where:不用讀取表中所有信息,僅通過索引就可以獲取所需數據

*Using temporary:表示MySQL需要使用臨時表來存儲結果集,group by ; order by

*Using filesort:包含 order by ,而且無法利用索引完成的排序操作稱為“文件排序”

*Using join buffer:該值強調了在獲取連接條件時沒有使用索引,並且需要連接緩衝區來存儲中間結果。

*Impossible where:這個值強調了where語句會導致沒有符合條件的行。

*Select tables optimized away:這個值意味著僅通過使用索引,優化器可能僅從聚合函數結果中返回一行

*No tables used:Query語句中使用from dual 或不含任何from子句

以上就是對EXPLAIN工具的一個介紹,瞭解了這個工具後,我們結合這個執行工具,來看一看哪些情況會導致這個索引失效!

第一種情況:針對聯合索引,是否遵循最左匹配原則;

我們user_name,user_password,mobile建立一個聯合索引,如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

聯合索引其實是建立了三個索引,也就是user_name的索引,user_name,user_password的索引,user_name,user_password,mobile的索引,最左匹配原則的意思,是否在語句中使用了最左建立的索引,也就是user_name的索引,演示一下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

當我們把user_name的查詢條件去掉之後,會是什麼情況呢?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

我們會看到索引已經失效了,用的是全表掃描,違背了最左匹配的原則,那麼對於查詢語句select * from tb_user where user_password='admin66666' and user_name='admin66666' and mobile='1234566666'會用到索引嗎?答案如下:

"
MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

在我們使用MySQL的過程中,隨著數據量越來越大,查詢顯得有些吃力,這時候就要針對查詢就行優化,針對查詢優化,通過給字段添加索引可以提高數據的讀取速度,提高項目的併發能力和抗壓能力。在上一篇我們講了給數據庫中的表添加索引,來提高它的查詢速度,但是會有另外一種情況出現,那就是我們給表中字段加了索引,但是查詢的時候依舊很慢,沒有什麼變化,這時就是因為建立的索引失效了,今天就來講一講索引失效的情況!

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於查看索引是否失效,MySQL數據庫針對每一條SQL語句,提供了一個查看它的執行計劃的工具,叫做EXPLAIN,咱們先來了解一下這個工具。首先說一下接下來用到的表,創建的表結構為:

CREATE TABLE `tb_user` (
`id` BIGINT (20),
`user_name` VARCHAR (200),
`user_password` VARCHAR (200),
`birth` DATETIME ,
`sex` CHAR (4),
\t\t\t\t `age` int(8),
`email` VARCHAR (200),
`mobile` VARCHAR (200),
`create_date` DATETIME ,
`update_date` DATETIME ,
`description` VARCHAR (800)
) ENGINE=INNODB;

創建一個存儲函數,向裡面插入一百萬條數據:

DELIMITER $$
CREATE
PROCEDURE insert_tb_user()
BEGIN
DECLARE i INT;
SET i=0;
WHILE i>=0 && i<= 1000000 DO
INSERT INTO tb_user
(`id`, `user_name`, `user_password`, `birth`, `sex`, `age`, `email`, `mobile`, `create_date`, `update_date`, `description`) VALUES
(i,concat('admin',i),concat('admin',i),NOW(),'M',i,'[email protected]',concat('12345',i),NOW(),NOW(),concat('超級管理員',i));
SET i=i + 1;
END WHILE;

END$$
DELIMITER ;
-- 執行存儲函數
call insert_tb_user()

生成的表數據如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

利用這個表,我們來介紹一下執行計劃和索引失效的情況。

首先來看一下執行計劃的結果是什麼樣的,執行計劃的查看,就是在查詢語句的前面加上EXPLAIN關鍵字就可以了:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於這些字段的意思,咱們一一來解釋:

一、 id,SELECT識別符。

*id相同時,執行順序由上至下

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

二、select_type,查詢中每個select子句的類型

*SIMPLE(簡單SELECT,不使用UNION或子查詢等)

*PRIMARY(子查詢中最外層查詢)

*UNION(UNION中的第二個或後面的SELECT語句)

*DEPENDENT UNION(UNION中的第二個或後面的SELECT語句)

*UNION RESULT(UNION的結果,union語句中第二個select開始後面所有select)

*SUBQUERY(子查詢中的第一個SELECT,結果不依賴於外部查詢)

*DEPENDENT SUBQUERY(子查詢中的第一個SELECT,依賴於外部查詢)

* DERIVED(派生表的SELECT, FROM子句的子查詢)

* UNCACHEABLE SUBQUERY(一個子查詢的結果不能被緩存,必須重新評估外鏈接的第一行)

三、 table,顯示這一步所訪問數據庫中表名稱。

四、type,對錶訪問方式

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

*index: Full Index Scan,index與ALL區別為index類型只遍歷索引樹

*range:只檢索給定範圍的行,使用一個索引來選擇行

*ref: 表示上述表的連接匹配條件,即哪些列或常量被用於查找索引列上的值

*eq_ref: 類似ref,區別就在使用的索引是唯一索引,對於每個索引鍵值,表中只有一條記錄匹配,簡單來說,就是多表連接中使用primary key或者 unique key作為關聯條件

*const、system: 當MySQL對查詢某部分進行優化,並轉換為一個常量時,使用這些類型訪問。如將主鍵置於where列表中,MySQL就能將該查詢轉換為一個常量,system是const類型的特例,當查詢的表只有一行的情況下,使用system

*NULL: MySQL在優化過程中分解語句,執行時甚至不用訪問表或索引,例如從一個索引列裡選取最小值可以通過單獨索引查找完成。

五、 possible_keys,可能使用的索引。

六、key,實際使用的索引

七、key_len,索引中使用的字節數,可通過該列計算查詢中使用的索引的長度

八、ref,列與索引的比較,表示上述表的連接匹配條件

九、rows,估算出結果集行數

十、Extra,MySQL解決查詢的詳細信息

*Using where:不用讀取表中所有信息,僅通過索引就可以獲取所需數據

*Using temporary:表示MySQL需要使用臨時表來存儲結果集,group by ; order by

*Using filesort:包含 order by ,而且無法利用索引完成的排序操作稱為“文件排序”

*Using join buffer:該值強調了在獲取連接條件時沒有使用索引,並且需要連接緩衝區來存儲中間結果。

*Impossible where:這個值強調了where語句會導致沒有符合條件的行。

*Select tables optimized away:這個值意味著僅通過使用索引,優化器可能僅從聚合函數結果中返回一行

*No tables used:Query語句中使用from dual 或不含任何from子句

以上就是對EXPLAIN工具的一個介紹,瞭解了這個工具後,我們結合這個執行工具,來看一看哪些情況會導致這個索引失效!

第一種情況:針對聯合索引,是否遵循最左匹配原則;

我們user_name,user_password,mobile建立一個聯合索引,如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

聯合索引其實是建立了三個索引,也就是user_name的索引,user_name,user_password的索引,user_name,user_password,mobile的索引,最左匹配原則的意思,是否在語句中使用了最左建立的索引,也就是user_name的索引,演示一下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

當我們把user_name的查詢條件去掉之後,會是什麼情況呢?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

我們會看到索引已經失效了,用的是全表掃描,違背了最左匹配的原則,那麼對於查詢語句select * from tb_user where user_password='admin66666' and user_name='admin66666' and mobile='1234566666'會用到索引嗎?答案如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

也是用到了聯合索引,這和你條件中寫的順序是沒有關係的!

第二種情況:在索引列上做了函數操作,會導致索引失效而導致全表掃描

我們先把那個聯合索引刪除掉,然後在user_name這一列上建立一個唯一索引:

"
MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

在我們使用MySQL的過程中,隨著數據量越來越大,查詢顯得有些吃力,這時候就要針對查詢就行優化,針對查詢優化,通過給字段添加索引可以提高數據的讀取速度,提高項目的併發能力和抗壓能力。在上一篇我們講了給數據庫中的表添加索引,來提高它的查詢速度,但是會有另外一種情況出現,那就是我們給表中字段加了索引,但是查詢的時候依舊很慢,沒有什麼變化,這時就是因為建立的索引失效了,今天就來講一講索引失效的情況!

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於查看索引是否失效,MySQL數據庫針對每一條SQL語句,提供了一個查看它的執行計劃的工具,叫做EXPLAIN,咱們先來了解一下這個工具。首先說一下接下來用到的表,創建的表結構為:

CREATE TABLE `tb_user` (
`id` BIGINT (20),
`user_name` VARCHAR (200),
`user_password` VARCHAR (200),
`birth` DATETIME ,
`sex` CHAR (4),
\t\t\t\t `age` int(8),
`email` VARCHAR (200),
`mobile` VARCHAR (200),
`create_date` DATETIME ,
`update_date` DATETIME ,
`description` VARCHAR (800)
) ENGINE=INNODB;

創建一個存儲函數,向裡面插入一百萬條數據:

DELIMITER $$
CREATE
PROCEDURE insert_tb_user()
BEGIN
DECLARE i INT;
SET i=0;
WHILE i>=0 && i<= 1000000 DO
INSERT INTO tb_user
(`id`, `user_name`, `user_password`, `birth`, `sex`, `age`, `email`, `mobile`, `create_date`, `update_date`, `description`) VALUES
(i,concat('admin',i),concat('admin',i),NOW(),'M',i,'[email protected]',concat('12345',i),NOW(),NOW(),concat('超級管理員',i));
SET i=i + 1;
END WHILE;

END$$
DELIMITER ;
-- 執行存儲函數
call insert_tb_user()

生成的表數據如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

利用這個表,我們來介紹一下執行計劃和索引失效的情況。

首先來看一下執行計劃的結果是什麼樣的,執行計劃的查看,就是在查詢語句的前面加上EXPLAIN關鍵字就可以了:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於這些字段的意思,咱們一一來解釋:

一、 id,SELECT識別符。

*id相同時,執行順序由上至下

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

二、select_type,查詢中每個select子句的類型

*SIMPLE(簡單SELECT,不使用UNION或子查詢等)

*PRIMARY(子查詢中最外層查詢)

*UNION(UNION中的第二個或後面的SELECT語句)

*DEPENDENT UNION(UNION中的第二個或後面的SELECT語句)

*UNION RESULT(UNION的結果,union語句中第二個select開始後面所有select)

*SUBQUERY(子查詢中的第一個SELECT,結果不依賴於外部查詢)

*DEPENDENT SUBQUERY(子查詢中的第一個SELECT,依賴於外部查詢)

* DERIVED(派生表的SELECT, FROM子句的子查詢)

* UNCACHEABLE SUBQUERY(一個子查詢的結果不能被緩存,必須重新評估外鏈接的第一行)

三、 table,顯示這一步所訪問數據庫中表名稱。

四、type,對錶訪問方式

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

*index: Full Index Scan,index與ALL區別為index類型只遍歷索引樹

*range:只檢索給定範圍的行,使用一個索引來選擇行

*ref: 表示上述表的連接匹配條件,即哪些列或常量被用於查找索引列上的值

*eq_ref: 類似ref,區別就在使用的索引是唯一索引,對於每個索引鍵值,表中只有一條記錄匹配,簡單來說,就是多表連接中使用primary key或者 unique key作為關聯條件

*const、system: 當MySQL對查詢某部分進行優化,並轉換為一個常量時,使用這些類型訪問。如將主鍵置於where列表中,MySQL就能將該查詢轉換為一個常量,system是const類型的特例,當查詢的表只有一行的情況下,使用system

*NULL: MySQL在優化過程中分解語句,執行時甚至不用訪問表或索引,例如從一個索引列裡選取最小值可以通過單獨索引查找完成。

五、 possible_keys,可能使用的索引。

六、key,實際使用的索引

七、key_len,索引中使用的字節數,可通過該列計算查詢中使用的索引的長度

八、ref,列與索引的比較,表示上述表的連接匹配條件

九、rows,估算出結果集行數

十、Extra,MySQL解決查詢的詳細信息

*Using where:不用讀取表中所有信息,僅通過索引就可以獲取所需數據

*Using temporary:表示MySQL需要使用臨時表來存儲結果集,group by ; order by

*Using filesort:包含 order by ,而且無法利用索引完成的排序操作稱為“文件排序”

*Using join buffer:該值強調了在獲取連接條件時沒有使用索引,並且需要連接緩衝區來存儲中間結果。

*Impossible where:這個值強調了where語句會導致沒有符合條件的行。

*Select tables optimized away:這個值意味著僅通過使用索引,優化器可能僅從聚合函數結果中返回一行

*No tables used:Query語句中使用from dual 或不含任何from子句

以上就是對EXPLAIN工具的一個介紹,瞭解了這個工具後,我們結合這個執行工具,來看一看哪些情況會導致這個索引失效!

第一種情況:針對聯合索引,是否遵循最左匹配原則;

我們user_name,user_password,mobile建立一個聯合索引,如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

聯合索引其實是建立了三個索引,也就是user_name的索引,user_name,user_password的索引,user_name,user_password,mobile的索引,最左匹配原則的意思,是否在語句中使用了最左建立的索引,也就是user_name的索引,演示一下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

當我們把user_name的查詢條件去掉之後,會是什麼情況呢?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

我們會看到索引已經失效了,用的是全表掃描,違背了最左匹配的原則,那麼對於查詢語句select * from tb_user where user_password='admin66666' and user_name='admin66666' and mobile='1234566666'會用到索引嗎?答案如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

也是用到了聯合索引,這和你條件中寫的順序是沒有關係的!

第二種情況:在索引列上做了函數操作,會導致索引失效而導致全表掃描

我們先把那個聯合索引刪除掉,然後在user_name這一列上建立一個唯一索引:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

"
MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

在我們使用MySQL的過程中,隨著數據量越來越大,查詢顯得有些吃力,這時候就要針對查詢就行優化,針對查詢優化,通過給字段添加索引可以提高數據的讀取速度,提高項目的併發能力和抗壓能力。在上一篇我們講了給數據庫中的表添加索引,來提高它的查詢速度,但是會有另外一種情況出現,那就是我們給表中字段加了索引,但是查詢的時候依舊很慢,沒有什麼變化,這時就是因為建立的索引失效了,今天就來講一講索引失效的情況!

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於查看索引是否失效,MySQL數據庫針對每一條SQL語句,提供了一個查看它的執行計劃的工具,叫做EXPLAIN,咱們先來了解一下這個工具。首先說一下接下來用到的表,創建的表結構為:

CREATE TABLE `tb_user` (
`id` BIGINT (20),
`user_name` VARCHAR (200),
`user_password` VARCHAR (200),
`birth` DATETIME ,
`sex` CHAR (4),
\t\t\t\t `age` int(8),
`email` VARCHAR (200),
`mobile` VARCHAR (200),
`create_date` DATETIME ,
`update_date` DATETIME ,
`description` VARCHAR (800)
) ENGINE=INNODB;

創建一個存儲函數,向裡面插入一百萬條數據:

DELIMITER $$
CREATE
PROCEDURE insert_tb_user()
BEGIN
DECLARE i INT;
SET i=0;
WHILE i>=0 && i<= 1000000 DO
INSERT INTO tb_user
(`id`, `user_name`, `user_password`, `birth`, `sex`, `age`, `email`, `mobile`, `create_date`, `update_date`, `description`) VALUES
(i,concat('admin',i),concat('admin',i),NOW(),'M',i,'[email protected]',concat('12345',i),NOW(),NOW(),concat('超級管理員',i));
SET i=i + 1;
END WHILE;

END$$
DELIMITER ;
-- 執行存儲函數
call insert_tb_user()

生成的表數據如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

利用這個表,我們來介紹一下執行計劃和索引失效的情況。

首先來看一下執行計劃的結果是什麼樣的,執行計劃的查看,就是在查詢語句的前面加上EXPLAIN關鍵字就可以了:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於這些字段的意思,咱們一一來解釋:

一、 id,SELECT識別符。

*id相同時,執行順序由上至下

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

二、select_type,查詢中每個select子句的類型

*SIMPLE(簡單SELECT,不使用UNION或子查詢等)

*PRIMARY(子查詢中最外層查詢)

*UNION(UNION中的第二個或後面的SELECT語句)

*DEPENDENT UNION(UNION中的第二個或後面的SELECT語句)

*UNION RESULT(UNION的結果,union語句中第二個select開始後面所有select)

*SUBQUERY(子查詢中的第一個SELECT,結果不依賴於外部查詢)

*DEPENDENT SUBQUERY(子查詢中的第一個SELECT,依賴於外部查詢)

* DERIVED(派生表的SELECT, FROM子句的子查詢)

* UNCACHEABLE SUBQUERY(一個子查詢的結果不能被緩存,必須重新評估外鏈接的第一行)

三、 table,顯示這一步所訪問數據庫中表名稱。

四、type,對錶訪問方式

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

*index: Full Index Scan,index與ALL區別為index類型只遍歷索引樹

*range:只檢索給定範圍的行,使用一個索引來選擇行

*ref: 表示上述表的連接匹配條件,即哪些列或常量被用於查找索引列上的值

*eq_ref: 類似ref,區別就在使用的索引是唯一索引,對於每個索引鍵值,表中只有一條記錄匹配,簡單來說,就是多表連接中使用primary key或者 unique key作為關聯條件

*const、system: 當MySQL對查詢某部分進行優化,並轉換為一個常量時,使用這些類型訪問。如將主鍵置於where列表中,MySQL就能將該查詢轉換為一個常量,system是const類型的特例,當查詢的表只有一行的情況下,使用system

*NULL: MySQL在優化過程中分解語句,執行時甚至不用訪問表或索引,例如從一個索引列裡選取最小值可以通過單獨索引查找完成。

五、 possible_keys,可能使用的索引。

六、key,實際使用的索引

七、key_len,索引中使用的字節數,可通過該列計算查詢中使用的索引的長度

八、ref,列與索引的比較,表示上述表的連接匹配條件

九、rows,估算出結果集行數

十、Extra,MySQL解決查詢的詳細信息

*Using where:不用讀取表中所有信息,僅通過索引就可以獲取所需數據

*Using temporary:表示MySQL需要使用臨時表來存儲結果集,group by ; order by

*Using filesort:包含 order by ,而且無法利用索引完成的排序操作稱為“文件排序”

*Using join buffer:該值強調了在獲取連接條件時沒有使用索引,並且需要連接緩衝區來存儲中間結果。

*Impossible where:這個值強調了where語句會導致沒有符合條件的行。

*Select tables optimized away:這個值意味著僅通過使用索引,優化器可能僅從聚合函數結果中返回一行

*No tables used:Query語句中使用from dual 或不含任何from子句

以上就是對EXPLAIN工具的一個介紹,瞭解了這個工具後,我們結合這個執行工具,來看一看哪些情況會導致這個索引失效!

第一種情況:針對聯合索引,是否遵循最左匹配原則;

我們user_name,user_password,mobile建立一個聯合索引,如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

聯合索引其實是建立了三個索引,也就是user_name的索引,user_name,user_password的索引,user_name,user_password,mobile的索引,最左匹配原則的意思,是否在語句中使用了最左建立的索引,也就是user_name的索引,演示一下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

當我們把user_name的查詢條件去掉之後,會是什麼情況呢?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

我們會看到索引已經失效了,用的是全表掃描,違背了最左匹配的原則,那麼對於查詢語句select * from tb_user where user_password='admin66666' and user_name='admin66666' and mobile='1234566666'會用到索引嗎?答案如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

也是用到了聯合索引,這和你條件中寫的順序是沒有關係的!

第二種情況:在索引列上做了函數操作,會導致索引失效而導致全表掃描

我們先把那個聯合索引刪除掉,然後在user_name這一列上建立一個唯一索引:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

"
MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

在我們使用MySQL的過程中,隨著數據量越來越大,查詢顯得有些吃力,這時候就要針對查詢就行優化,針對查詢優化,通過給字段添加索引可以提高數據的讀取速度,提高項目的併發能力和抗壓能力。在上一篇我們講了給數據庫中的表添加索引,來提高它的查詢速度,但是會有另外一種情況出現,那就是我們給表中字段加了索引,但是查詢的時候依舊很慢,沒有什麼變化,這時就是因為建立的索引失效了,今天就來講一講索引失效的情況!

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於查看索引是否失效,MySQL數據庫針對每一條SQL語句,提供了一個查看它的執行計劃的工具,叫做EXPLAIN,咱們先來了解一下這個工具。首先說一下接下來用到的表,創建的表結構為:

CREATE TABLE `tb_user` (
`id` BIGINT (20),
`user_name` VARCHAR (200),
`user_password` VARCHAR (200),
`birth` DATETIME ,
`sex` CHAR (4),
\t\t\t\t `age` int(8),
`email` VARCHAR (200),
`mobile` VARCHAR (200),
`create_date` DATETIME ,
`update_date` DATETIME ,
`description` VARCHAR (800)
) ENGINE=INNODB;

創建一個存儲函數,向裡面插入一百萬條數據:

DELIMITER $$
CREATE
PROCEDURE insert_tb_user()
BEGIN
DECLARE i INT;
SET i=0;
WHILE i>=0 && i<= 1000000 DO
INSERT INTO tb_user
(`id`, `user_name`, `user_password`, `birth`, `sex`, `age`, `email`, `mobile`, `create_date`, `update_date`, `description`) VALUES
(i,concat('admin',i),concat('admin',i),NOW(),'M',i,'[email protected]',concat('12345',i),NOW(),NOW(),concat('超級管理員',i));
SET i=i + 1;
END WHILE;

END$$
DELIMITER ;
-- 執行存儲函數
call insert_tb_user()

生成的表數據如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

利用這個表,我們來介紹一下執行計劃和索引失效的情況。

首先來看一下執行計劃的結果是什麼樣的,執行計劃的查看,就是在查詢語句的前面加上EXPLAIN關鍵字就可以了:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於這些字段的意思,咱們一一來解釋:

一、 id,SELECT識別符。

*id相同時,執行順序由上至下

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

二、select_type,查詢中每個select子句的類型

*SIMPLE(簡單SELECT,不使用UNION或子查詢等)

*PRIMARY(子查詢中最外層查詢)

*UNION(UNION中的第二個或後面的SELECT語句)

*DEPENDENT UNION(UNION中的第二個或後面的SELECT語句)

*UNION RESULT(UNION的結果,union語句中第二個select開始後面所有select)

*SUBQUERY(子查詢中的第一個SELECT,結果不依賴於外部查詢)

*DEPENDENT SUBQUERY(子查詢中的第一個SELECT,依賴於外部查詢)

* DERIVED(派生表的SELECT, FROM子句的子查詢)

* UNCACHEABLE SUBQUERY(一個子查詢的結果不能被緩存,必須重新評估外鏈接的第一行)

三、 table,顯示這一步所訪問數據庫中表名稱。

四、type,對錶訪問方式

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

*index: Full Index Scan,index與ALL區別為index類型只遍歷索引樹

*range:只檢索給定範圍的行,使用一個索引來選擇行

*ref: 表示上述表的連接匹配條件,即哪些列或常量被用於查找索引列上的值

*eq_ref: 類似ref,區別就在使用的索引是唯一索引,對於每個索引鍵值,表中只有一條記錄匹配,簡單來說,就是多表連接中使用primary key或者 unique key作為關聯條件

*const、system: 當MySQL對查詢某部分進行優化,並轉換為一個常量時,使用這些類型訪問。如將主鍵置於where列表中,MySQL就能將該查詢轉換為一個常量,system是const類型的特例,當查詢的表只有一行的情況下,使用system

*NULL: MySQL在優化過程中分解語句,執行時甚至不用訪問表或索引,例如從一個索引列裡選取最小值可以通過單獨索引查找完成。

五、 possible_keys,可能使用的索引。

六、key,實際使用的索引

七、key_len,索引中使用的字節數,可通過該列計算查詢中使用的索引的長度

八、ref,列與索引的比較,表示上述表的連接匹配條件

九、rows,估算出結果集行數

十、Extra,MySQL解決查詢的詳細信息

*Using where:不用讀取表中所有信息,僅通過索引就可以獲取所需數據

*Using temporary:表示MySQL需要使用臨時表來存儲結果集,group by ; order by

*Using filesort:包含 order by ,而且無法利用索引完成的排序操作稱為“文件排序”

*Using join buffer:該值強調了在獲取連接條件時沒有使用索引,並且需要連接緩衝區來存儲中間結果。

*Impossible where:這個值強調了where語句會導致沒有符合條件的行。

*Select tables optimized away:這個值意味著僅通過使用索引,優化器可能僅從聚合函數結果中返回一行

*No tables used:Query語句中使用from dual 或不含任何from子句

以上就是對EXPLAIN工具的一個介紹,瞭解了這個工具後,我們結合這個執行工具,來看一看哪些情況會導致這個索引失效!

第一種情況:針對聯合索引,是否遵循最左匹配原則;

我們user_name,user_password,mobile建立一個聯合索引,如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

聯合索引其實是建立了三個索引,也就是user_name的索引,user_name,user_password的索引,user_name,user_password,mobile的索引,最左匹配原則的意思,是否在語句中使用了最左建立的索引,也就是user_name的索引,演示一下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

當我們把user_name的查詢條件去掉之後,會是什麼情況呢?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

我們會看到索引已經失效了,用的是全表掃描,違背了最左匹配的原則,那麼對於查詢語句select * from tb_user where user_password='admin66666' and user_name='admin66666' and mobile='1234566666'會用到索引嗎?答案如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

也是用到了聯合索引,這和你條件中寫的順序是沒有關係的!

第二種情況:在索引列上做了函數操作,會導致索引失效而導致全表掃描

我們先把那個聯合索引刪除掉,然後在user_name這一列上建立一個唯一索引:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

先不在索引列上做函數操作,執行計劃如下:

"
MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

在我們使用MySQL的過程中,隨著數據量越來越大,查詢顯得有些吃力,這時候就要針對查詢就行優化,針對查詢優化,通過給字段添加索引可以提高數據的讀取速度,提高項目的併發能力和抗壓能力。在上一篇我們講了給數據庫中的表添加索引,來提高它的查詢速度,但是會有另外一種情況出現,那就是我們給表中字段加了索引,但是查詢的時候依舊很慢,沒有什麼變化,這時就是因為建立的索引失效了,今天就來講一講索引失效的情況!

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於查看索引是否失效,MySQL數據庫針對每一條SQL語句,提供了一個查看它的執行計劃的工具,叫做EXPLAIN,咱們先來了解一下這個工具。首先說一下接下來用到的表,創建的表結構為:

CREATE TABLE `tb_user` (
`id` BIGINT (20),
`user_name` VARCHAR (200),
`user_password` VARCHAR (200),
`birth` DATETIME ,
`sex` CHAR (4),
\t\t\t\t `age` int(8),
`email` VARCHAR (200),
`mobile` VARCHAR (200),
`create_date` DATETIME ,
`update_date` DATETIME ,
`description` VARCHAR (800)
) ENGINE=INNODB;

創建一個存儲函數,向裡面插入一百萬條數據:

DELIMITER $$
CREATE
PROCEDURE insert_tb_user()
BEGIN
DECLARE i INT;
SET i=0;
WHILE i>=0 && i<= 1000000 DO
INSERT INTO tb_user
(`id`, `user_name`, `user_password`, `birth`, `sex`, `age`, `email`, `mobile`, `create_date`, `update_date`, `description`) VALUES
(i,concat('admin',i),concat('admin',i),NOW(),'M',i,'[email protected]',concat('12345',i),NOW(),NOW(),concat('超級管理員',i));
SET i=i + 1;
END WHILE;

END$$
DELIMITER ;
-- 執行存儲函數
call insert_tb_user()

生成的表數據如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

利用這個表,我們來介紹一下執行計劃和索引失效的情況。

首先來看一下執行計劃的結果是什麼樣的,執行計劃的查看,就是在查詢語句的前面加上EXPLAIN關鍵字就可以了:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於這些字段的意思,咱們一一來解釋:

一、 id,SELECT識別符。

*id相同時,執行順序由上至下

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

二、select_type,查詢中每個select子句的類型

*SIMPLE(簡單SELECT,不使用UNION或子查詢等)

*PRIMARY(子查詢中最外層查詢)

*UNION(UNION中的第二個或後面的SELECT語句)

*DEPENDENT UNION(UNION中的第二個或後面的SELECT語句)

*UNION RESULT(UNION的結果,union語句中第二個select開始後面所有select)

*SUBQUERY(子查詢中的第一個SELECT,結果不依賴於外部查詢)

*DEPENDENT SUBQUERY(子查詢中的第一個SELECT,依賴於外部查詢)

* DERIVED(派生表的SELECT, FROM子句的子查詢)

* UNCACHEABLE SUBQUERY(一個子查詢的結果不能被緩存,必須重新評估外鏈接的第一行)

三、 table,顯示這一步所訪問數據庫中表名稱。

四、type,對錶訪問方式

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

*index: Full Index Scan,index與ALL區別為index類型只遍歷索引樹

*range:只檢索給定範圍的行,使用一個索引來選擇行

*ref: 表示上述表的連接匹配條件,即哪些列或常量被用於查找索引列上的值

*eq_ref: 類似ref,區別就在使用的索引是唯一索引,對於每個索引鍵值,表中只有一條記錄匹配,簡單來說,就是多表連接中使用primary key或者 unique key作為關聯條件

*const、system: 當MySQL對查詢某部分進行優化,並轉換為一個常量時,使用這些類型訪問。如將主鍵置於where列表中,MySQL就能將該查詢轉換為一個常量,system是const類型的特例,當查詢的表只有一行的情況下,使用system

*NULL: MySQL在優化過程中分解語句,執行時甚至不用訪問表或索引,例如從一個索引列裡選取最小值可以通過單獨索引查找完成。

五、 possible_keys,可能使用的索引。

六、key,實際使用的索引

七、key_len,索引中使用的字節數,可通過該列計算查詢中使用的索引的長度

八、ref,列與索引的比較,表示上述表的連接匹配條件

九、rows,估算出結果集行數

十、Extra,MySQL解決查詢的詳細信息

*Using where:不用讀取表中所有信息,僅通過索引就可以獲取所需數據

*Using temporary:表示MySQL需要使用臨時表來存儲結果集,group by ; order by

*Using filesort:包含 order by ,而且無法利用索引完成的排序操作稱為“文件排序”

*Using join buffer:該值強調了在獲取連接條件時沒有使用索引,並且需要連接緩衝區來存儲中間結果。

*Impossible where:這個值強調了where語句會導致沒有符合條件的行。

*Select tables optimized away:這個值意味著僅通過使用索引,優化器可能僅從聚合函數結果中返回一行

*No tables used:Query語句中使用from dual 或不含任何from子句

以上就是對EXPLAIN工具的一個介紹,瞭解了這個工具後,我們結合這個執行工具,來看一看哪些情況會導致這個索引失效!

第一種情況:針對聯合索引,是否遵循最左匹配原則;

我們user_name,user_password,mobile建立一個聯合索引,如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

聯合索引其實是建立了三個索引,也就是user_name的索引,user_name,user_password的索引,user_name,user_password,mobile的索引,最左匹配原則的意思,是否在語句中使用了最左建立的索引,也就是user_name的索引,演示一下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

當我們把user_name的查詢條件去掉之後,會是什麼情況呢?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

我們會看到索引已經失效了,用的是全表掃描,違背了最左匹配的原則,那麼對於查詢語句select * from tb_user where user_password='admin66666' and user_name='admin66666' and mobile='1234566666'會用到索引嗎?答案如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

也是用到了聯合索引,這和你條件中寫的順序是沒有關係的!

第二種情況:在索引列上做了函數操作,會導致索引失效而導致全表掃描

我們先把那個聯合索引刪除掉,然後在user_name這一列上建立一個唯一索引:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

先不在索引列上做函數操作,執行計劃如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

很顯然使用了索引,那麼索引列進行函數操作呢?例如做一個字符拼接的操作:

"
MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

在我們使用MySQL的過程中,隨著數據量越來越大,查詢顯得有些吃力,這時候就要針對查詢就行優化,針對查詢優化,通過給字段添加索引可以提高數據的讀取速度,提高項目的併發能力和抗壓能力。在上一篇我們講了給數據庫中的表添加索引,來提高它的查詢速度,但是會有另外一種情況出現,那就是我們給表中字段加了索引,但是查詢的時候依舊很慢,沒有什麼變化,這時就是因為建立的索引失效了,今天就來講一講索引失效的情況!

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於查看索引是否失效,MySQL數據庫針對每一條SQL語句,提供了一個查看它的執行計劃的工具,叫做EXPLAIN,咱們先來了解一下這個工具。首先說一下接下來用到的表,創建的表結構為:

CREATE TABLE `tb_user` (
`id` BIGINT (20),
`user_name` VARCHAR (200),
`user_password` VARCHAR (200),
`birth` DATETIME ,
`sex` CHAR (4),
\t\t\t\t `age` int(8),
`email` VARCHAR (200),
`mobile` VARCHAR (200),
`create_date` DATETIME ,
`update_date` DATETIME ,
`description` VARCHAR (800)
) ENGINE=INNODB;

創建一個存儲函數,向裡面插入一百萬條數據:

DELIMITER $$
CREATE
PROCEDURE insert_tb_user()
BEGIN
DECLARE i INT;
SET i=0;
WHILE i>=0 && i<= 1000000 DO
INSERT INTO tb_user
(`id`, `user_name`, `user_password`, `birth`, `sex`, `age`, `email`, `mobile`, `create_date`, `update_date`, `description`) VALUES
(i,concat('admin',i),concat('admin',i),NOW(),'M',i,'[email protected]',concat('12345',i),NOW(),NOW(),concat('超級管理員',i));
SET i=i + 1;
END WHILE;

END$$
DELIMITER ;
-- 執行存儲函數
call insert_tb_user()

生成的表數據如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

利用這個表,我們來介紹一下執行計劃和索引失效的情況。

首先來看一下執行計劃的結果是什麼樣的,執行計劃的查看,就是在查詢語句的前面加上EXPLAIN關鍵字就可以了:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於這些字段的意思,咱們一一來解釋:

一、 id,SELECT識別符。

*id相同時,執行順序由上至下

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

二、select_type,查詢中每個select子句的類型

*SIMPLE(簡單SELECT,不使用UNION或子查詢等)

*PRIMARY(子查詢中最外層查詢)

*UNION(UNION中的第二個或後面的SELECT語句)

*DEPENDENT UNION(UNION中的第二個或後面的SELECT語句)

*UNION RESULT(UNION的結果,union語句中第二個select開始後面所有select)

*SUBQUERY(子查詢中的第一個SELECT,結果不依賴於外部查詢)

*DEPENDENT SUBQUERY(子查詢中的第一個SELECT,依賴於外部查詢)

* DERIVED(派生表的SELECT, FROM子句的子查詢)

* UNCACHEABLE SUBQUERY(一個子查詢的結果不能被緩存,必須重新評估外鏈接的第一行)

三、 table,顯示這一步所訪問數據庫中表名稱。

四、type,對錶訪問方式

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

*index: Full Index Scan,index與ALL區別為index類型只遍歷索引樹

*range:只檢索給定範圍的行,使用一個索引來選擇行

*ref: 表示上述表的連接匹配條件,即哪些列或常量被用於查找索引列上的值

*eq_ref: 類似ref,區別就在使用的索引是唯一索引,對於每個索引鍵值,表中只有一條記錄匹配,簡單來說,就是多表連接中使用primary key或者 unique key作為關聯條件

*const、system: 當MySQL對查詢某部分進行優化,並轉換為一個常量時,使用這些類型訪問。如將主鍵置於where列表中,MySQL就能將該查詢轉換為一個常量,system是const類型的特例,當查詢的表只有一行的情況下,使用system

*NULL: MySQL在優化過程中分解語句,執行時甚至不用訪問表或索引,例如從一個索引列裡選取最小值可以通過單獨索引查找完成。

五、 possible_keys,可能使用的索引。

六、key,實際使用的索引

七、key_len,索引中使用的字節數,可通過該列計算查詢中使用的索引的長度

八、ref,列與索引的比較,表示上述表的連接匹配條件

九、rows,估算出結果集行數

十、Extra,MySQL解決查詢的詳細信息

*Using where:不用讀取表中所有信息,僅通過索引就可以獲取所需數據

*Using temporary:表示MySQL需要使用臨時表來存儲結果集,group by ; order by

*Using filesort:包含 order by ,而且無法利用索引完成的排序操作稱為“文件排序”

*Using join buffer:該值強調了在獲取連接條件時沒有使用索引,並且需要連接緩衝區來存儲中間結果。

*Impossible where:這個值強調了where語句會導致沒有符合條件的行。

*Select tables optimized away:這個值意味著僅通過使用索引,優化器可能僅從聚合函數結果中返回一行

*No tables used:Query語句中使用from dual 或不含任何from子句

以上就是對EXPLAIN工具的一個介紹,瞭解了這個工具後,我們結合這個執行工具,來看一看哪些情況會導致這個索引失效!

第一種情況:針對聯合索引,是否遵循最左匹配原則;

我們user_name,user_password,mobile建立一個聯合索引,如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

聯合索引其實是建立了三個索引,也就是user_name的索引,user_name,user_password的索引,user_name,user_password,mobile的索引,最左匹配原則的意思,是否在語句中使用了最左建立的索引,也就是user_name的索引,演示一下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

當我們把user_name的查詢條件去掉之後,會是什麼情況呢?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

我們會看到索引已經失效了,用的是全表掃描,違背了最左匹配的原則,那麼對於查詢語句select * from tb_user where user_password='admin66666' and user_name='admin66666' and mobile='1234566666'會用到索引嗎?答案如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

也是用到了聯合索引,這和你條件中寫的順序是沒有關係的!

第二種情況:在索引列上做了函數操作,會導致索引失效而導致全表掃描

我們先把那個聯合索引刪除掉,然後在user_name這一列上建立一個唯一索引:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

先不在索引列上做函數操作,執行計劃如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

很顯然使用了索引,那麼索引列進行函數操作呢?例如做一個字符拼接的操作:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

第三種情況:語句中like查詢是以%開頭,索引會失效變成全表掃描,覆蓋索引。

示例如下:

"
MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

在我們使用MySQL的過程中,隨著數據量越來越大,查詢顯得有些吃力,這時候就要針對查詢就行優化,針對查詢優化,通過給字段添加索引可以提高數據的讀取速度,提高項目的併發能力和抗壓能力。在上一篇我們講了給數據庫中的表添加索引,來提高它的查詢速度,但是會有另外一種情況出現,那就是我們給表中字段加了索引,但是查詢的時候依舊很慢,沒有什麼變化,這時就是因為建立的索引失效了,今天就來講一講索引失效的情況!

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於查看索引是否失效,MySQL數據庫針對每一條SQL語句,提供了一個查看它的執行計劃的工具,叫做EXPLAIN,咱們先來了解一下這個工具。首先說一下接下來用到的表,創建的表結構為:

CREATE TABLE `tb_user` (
`id` BIGINT (20),
`user_name` VARCHAR (200),
`user_password` VARCHAR (200),
`birth` DATETIME ,
`sex` CHAR (4),
\t\t\t\t `age` int(8),
`email` VARCHAR (200),
`mobile` VARCHAR (200),
`create_date` DATETIME ,
`update_date` DATETIME ,
`description` VARCHAR (800)
) ENGINE=INNODB;

創建一個存儲函數,向裡面插入一百萬條數據:

DELIMITER $$
CREATE
PROCEDURE insert_tb_user()
BEGIN
DECLARE i INT;
SET i=0;
WHILE i>=0 && i<= 1000000 DO
INSERT INTO tb_user
(`id`, `user_name`, `user_password`, `birth`, `sex`, `age`, `email`, `mobile`, `create_date`, `update_date`, `description`) VALUES
(i,concat('admin',i),concat('admin',i),NOW(),'M',i,'[email protected]',concat('12345',i),NOW(),NOW(),concat('超級管理員',i));
SET i=i + 1;
END WHILE;

END$$
DELIMITER ;
-- 執行存儲函數
call insert_tb_user()

生成的表數據如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

利用這個表,我們來介紹一下執行計劃和索引失效的情況。

首先來看一下執行計劃的結果是什麼樣的,執行計劃的查看,就是在查詢語句的前面加上EXPLAIN關鍵字就可以了:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於這些字段的意思,咱們一一來解釋:

一、 id,SELECT識別符。

*id相同時,執行順序由上至下

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

二、select_type,查詢中每個select子句的類型

*SIMPLE(簡單SELECT,不使用UNION或子查詢等)

*PRIMARY(子查詢中最外層查詢)

*UNION(UNION中的第二個或後面的SELECT語句)

*DEPENDENT UNION(UNION中的第二個或後面的SELECT語句)

*UNION RESULT(UNION的結果,union語句中第二個select開始後面所有select)

*SUBQUERY(子查詢中的第一個SELECT,結果不依賴於外部查詢)

*DEPENDENT SUBQUERY(子查詢中的第一個SELECT,依賴於外部查詢)

* DERIVED(派生表的SELECT, FROM子句的子查詢)

* UNCACHEABLE SUBQUERY(一個子查詢的結果不能被緩存,必須重新評估外鏈接的第一行)

三、 table,顯示這一步所訪問數據庫中表名稱。

四、type,對錶訪問方式

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

*index: Full Index Scan,index與ALL區別為index類型只遍歷索引樹

*range:只檢索給定範圍的行,使用一個索引來選擇行

*ref: 表示上述表的連接匹配條件,即哪些列或常量被用於查找索引列上的值

*eq_ref: 類似ref,區別就在使用的索引是唯一索引,對於每個索引鍵值,表中只有一條記錄匹配,簡單來說,就是多表連接中使用primary key或者 unique key作為關聯條件

*const、system: 當MySQL對查詢某部分進行優化,並轉換為一個常量時,使用這些類型訪問。如將主鍵置於where列表中,MySQL就能將該查詢轉換為一個常量,system是const類型的特例,當查詢的表只有一行的情況下,使用system

*NULL: MySQL在優化過程中分解語句,執行時甚至不用訪問表或索引,例如從一個索引列裡選取最小值可以通過單獨索引查找完成。

五、 possible_keys,可能使用的索引。

六、key,實際使用的索引

七、key_len,索引中使用的字節數,可通過該列計算查詢中使用的索引的長度

八、ref,列與索引的比較,表示上述表的連接匹配條件

九、rows,估算出結果集行數

十、Extra,MySQL解決查詢的詳細信息

*Using where:不用讀取表中所有信息,僅通過索引就可以獲取所需數據

*Using temporary:表示MySQL需要使用臨時表來存儲結果集,group by ; order by

*Using filesort:包含 order by ,而且無法利用索引完成的排序操作稱為“文件排序”

*Using join buffer:該值強調了在獲取連接條件時沒有使用索引,並且需要連接緩衝區來存儲中間結果。

*Impossible where:這個值強調了where語句會導致沒有符合條件的行。

*Select tables optimized away:這個值意味著僅通過使用索引,優化器可能僅從聚合函數結果中返回一行

*No tables used:Query語句中使用from dual 或不含任何from子句

以上就是對EXPLAIN工具的一個介紹,瞭解了這個工具後,我們結合這個執行工具,來看一看哪些情況會導致這個索引失效!

第一種情況:針對聯合索引,是否遵循最左匹配原則;

我們user_name,user_password,mobile建立一個聯合索引,如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

聯合索引其實是建立了三個索引,也就是user_name的索引,user_name,user_password的索引,user_name,user_password,mobile的索引,最左匹配原則的意思,是否在語句中使用了最左建立的索引,也就是user_name的索引,演示一下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

當我們把user_name的查詢條件去掉之後,會是什麼情況呢?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

我們會看到索引已經失效了,用的是全表掃描,違背了最左匹配的原則,那麼對於查詢語句select * from tb_user where user_password='admin66666' and user_name='admin66666' and mobile='1234566666'會用到索引嗎?答案如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

也是用到了聯合索引,這和你條件中寫的順序是沒有關係的!

第二種情況:在索引列上做了函數操作,會導致索引失效而導致全表掃描

我們先把那個聯合索引刪除掉,然後在user_name這一列上建立一個唯一索引:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

先不在索引列上做函數操作,執行計劃如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

很顯然使用了索引,那麼索引列進行函數操作呢?例如做一個字符拼接的操作:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

第三種情況:語句中like查詢是以%開頭,索引會失效變成全表掃描,覆蓋索引。

示例如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

如果模糊查詢不是以%開頭的,那麼也是可以用到索引的:

"
MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

在我們使用MySQL的過程中,隨著數據量越來越大,查詢顯得有些吃力,這時候就要針對查詢就行優化,針對查詢優化,通過給字段添加索引可以提高數據的讀取速度,提高項目的併發能力和抗壓能力。在上一篇我們講了給數據庫中的表添加索引,來提高它的查詢速度,但是會有另外一種情況出現,那就是我們給表中字段加了索引,但是查詢的時候依舊很慢,沒有什麼變化,這時就是因為建立的索引失效了,今天就來講一講索引失效的情況!

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於查看索引是否失效,MySQL數據庫針對每一條SQL語句,提供了一個查看它的執行計劃的工具,叫做EXPLAIN,咱們先來了解一下這個工具。首先說一下接下來用到的表,創建的表結構為:

CREATE TABLE `tb_user` (
`id` BIGINT (20),
`user_name` VARCHAR (200),
`user_password` VARCHAR (200),
`birth` DATETIME ,
`sex` CHAR (4),
\t\t\t\t `age` int(8),
`email` VARCHAR (200),
`mobile` VARCHAR (200),
`create_date` DATETIME ,
`update_date` DATETIME ,
`description` VARCHAR (800)
) ENGINE=INNODB;

創建一個存儲函數,向裡面插入一百萬條數據:

DELIMITER $$
CREATE
PROCEDURE insert_tb_user()
BEGIN
DECLARE i INT;
SET i=0;
WHILE i>=0 && i<= 1000000 DO
INSERT INTO tb_user
(`id`, `user_name`, `user_password`, `birth`, `sex`, `age`, `email`, `mobile`, `create_date`, `update_date`, `description`) VALUES
(i,concat('admin',i),concat('admin',i),NOW(),'M',i,'[email protected]',concat('12345',i),NOW(),NOW(),concat('超級管理員',i));
SET i=i + 1;
END WHILE;

END$$
DELIMITER ;
-- 執行存儲函數
call insert_tb_user()

生成的表數據如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

利用這個表,我們來介紹一下執行計劃和索引失效的情況。

首先來看一下執行計劃的結果是什麼樣的,執行計劃的查看,就是在查詢語句的前面加上EXPLAIN關鍵字就可以了:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於這些字段的意思,咱們一一來解釋:

一、 id,SELECT識別符。

*id相同時,執行順序由上至下

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

二、select_type,查詢中每個select子句的類型

*SIMPLE(簡單SELECT,不使用UNION或子查詢等)

*PRIMARY(子查詢中最外層查詢)

*UNION(UNION中的第二個或後面的SELECT語句)

*DEPENDENT UNION(UNION中的第二個或後面的SELECT語句)

*UNION RESULT(UNION的結果,union語句中第二個select開始後面所有select)

*SUBQUERY(子查詢中的第一個SELECT,結果不依賴於外部查詢)

*DEPENDENT SUBQUERY(子查詢中的第一個SELECT,依賴於外部查詢)

* DERIVED(派生表的SELECT, FROM子句的子查詢)

* UNCACHEABLE SUBQUERY(一個子查詢的結果不能被緩存,必須重新評估外鏈接的第一行)

三、 table,顯示這一步所訪問數據庫中表名稱。

四、type,對錶訪問方式

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

*index: Full Index Scan,index與ALL區別為index類型只遍歷索引樹

*range:只檢索給定範圍的行,使用一個索引來選擇行

*ref: 表示上述表的連接匹配條件,即哪些列或常量被用於查找索引列上的值

*eq_ref: 類似ref,區別就在使用的索引是唯一索引,對於每個索引鍵值,表中只有一條記錄匹配,簡單來說,就是多表連接中使用primary key或者 unique key作為關聯條件

*const、system: 當MySQL對查詢某部分進行優化,並轉換為一個常量時,使用這些類型訪問。如將主鍵置於where列表中,MySQL就能將該查詢轉換為一個常量,system是const類型的特例,當查詢的表只有一行的情況下,使用system

*NULL: MySQL在優化過程中分解語句,執行時甚至不用訪問表或索引,例如從一個索引列裡選取最小值可以通過單獨索引查找完成。

五、 possible_keys,可能使用的索引。

六、key,實際使用的索引

七、key_len,索引中使用的字節數,可通過該列計算查詢中使用的索引的長度

八、ref,列與索引的比較,表示上述表的連接匹配條件

九、rows,估算出結果集行數

十、Extra,MySQL解決查詢的詳細信息

*Using where:不用讀取表中所有信息,僅通過索引就可以獲取所需數據

*Using temporary:表示MySQL需要使用臨時表來存儲結果集,group by ; order by

*Using filesort:包含 order by ,而且無法利用索引完成的排序操作稱為“文件排序”

*Using join buffer:該值強調了在獲取連接條件時沒有使用索引,並且需要連接緩衝區來存儲中間結果。

*Impossible where:這個值強調了where語句會導致沒有符合條件的行。

*Select tables optimized away:這個值意味著僅通過使用索引,優化器可能僅從聚合函數結果中返回一行

*No tables used:Query語句中使用from dual 或不含任何from子句

以上就是對EXPLAIN工具的一個介紹,瞭解了這個工具後,我們結合這個執行工具,來看一看哪些情況會導致這個索引失效!

第一種情況:針對聯合索引,是否遵循最左匹配原則;

我們user_name,user_password,mobile建立一個聯合索引,如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

聯合索引其實是建立了三個索引,也就是user_name的索引,user_name,user_password的索引,user_name,user_password,mobile的索引,最左匹配原則的意思,是否在語句中使用了最左建立的索引,也就是user_name的索引,演示一下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

當我們把user_name的查詢條件去掉之後,會是什麼情況呢?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

我們會看到索引已經失效了,用的是全表掃描,違背了最左匹配的原則,那麼對於查詢語句select * from tb_user where user_password='admin66666' and user_name='admin66666' and mobile='1234566666'會用到索引嗎?答案如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

也是用到了聯合索引,這和你條件中寫的順序是沒有關係的!

第二種情況:在索引列上做了函數操作,會導致索引失效而導致全表掃描

我們先把那個聯合索引刪除掉,然後在user_name這一列上建立一個唯一索引:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

先不在索引列上做函數操作,執行計劃如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

很顯然使用了索引,那麼索引列進行函數操作呢?例如做一個字符拼接的操作:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

第三種情況:語句中like查詢是以%開頭,索引會失效變成全表掃描,覆蓋索引。

示例如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

如果模糊查詢不是以%開頭的,那麼也是可以用到索引的:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

第四種情況:使用is not null 會導致無法使用索引

示例如下:

"
MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

在我們使用MySQL的過程中,隨著數據量越來越大,查詢顯得有些吃力,這時候就要針對查詢就行優化,針對查詢優化,通過給字段添加索引可以提高數據的讀取速度,提高項目的併發能力和抗壓能力。在上一篇我們講了給數據庫中的表添加索引,來提高它的查詢速度,但是會有另外一種情況出現,那就是我們給表中字段加了索引,但是查詢的時候依舊很慢,沒有什麼變化,這時就是因為建立的索引失效了,今天就來講一講索引失效的情況!

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於查看索引是否失效,MySQL數據庫針對每一條SQL語句,提供了一個查看它的執行計劃的工具,叫做EXPLAIN,咱們先來了解一下這個工具。首先說一下接下來用到的表,創建的表結構為:

CREATE TABLE `tb_user` (
`id` BIGINT (20),
`user_name` VARCHAR (200),
`user_password` VARCHAR (200),
`birth` DATETIME ,
`sex` CHAR (4),
\t\t\t\t `age` int(8),
`email` VARCHAR (200),
`mobile` VARCHAR (200),
`create_date` DATETIME ,
`update_date` DATETIME ,
`description` VARCHAR (800)
) ENGINE=INNODB;

創建一個存儲函數,向裡面插入一百萬條數據:

DELIMITER $$
CREATE
PROCEDURE insert_tb_user()
BEGIN
DECLARE i INT;
SET i=0;
WHILE i>=0 && i<= 1000000 DO
INSERT INTO tb_user
(`id`, `user_name`, `user_password`, `birth`, `sex`, `age`, `email`, `mobile`, `create_date`, `update_date`, `description`) VALUES
(i,concat('admin',i),concat('admin',i),NOW(),'M',i,'[email protected]',concat('12345',i),NOW(),NOW(),concat('超級管理員',i));
SET i=i + 1;
END WHILE;

END$$
DELIMITER ;
-- 執行存儲函數
call insert_tb_user()

生成的表數據如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

利用這個表,我們來介紹一下執行計劃和索引失效的情況。

首先來看一下執行計劃的結果是什麼樣的,執行計劃的查看,就是在查詢語句的前面加上EXPLAIN關鍵字就可以了:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於這些字段的意思,咱們一一來解釋:

一、 id,SELECT識別符。

*id相同時,執行順序由上至下

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

二、select_type,查詢中每個select子句的類型

*SIMPLE(簡單SELECT,不使用UNION或子查詢等)

*PRIMARY(子查詢中最外層查詢)

*UNION(UNION中的第二個或後面的SELECT語句)

*DEPENDENT UNION(UNION中的第二個或後面的SELECT語句)

*UNION RESULT(UNION的結果,union語句中第二個select開始後面所有select)

*SUBQUERY(子查詢中的第一個SELECT,結果不依賴於外部查詢)

*DEPENDENT SUBQUERY(子查詢中的第一個SELECT,依賴於外部查詢)

* DERIVED(派生表的SELECT, FROM子句的子查詢)

* UNCACHEABLE SUBQUERY(一個子查詢的結果不能被緩存,必須重新評估外鏈接的第一行)

三、 table,顯示這一步所訪問數據庫中表名稱。

四、type,對錶訪問方式

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

*index: Full Index Scan,index與ALL區別為index類型只遍歷索引樹

*range:只檢索給定範圍的行,使用一個索引來選擇行

*ref: 表示上述表的連接匹配條件,即哪些列或常量被用於查找索引列上的值

*eq_ref: 類似ref,區別就在使用的索引是唯一索引,對於每個索引鍵值,表中只有一條記錄匹配,簡單來說,就是多表連接中使用primary key或者 unique key作為關聯條件

*const、system: 當MySQL對查詢某部分進行優化,並轉換為一個常量時,使用這些類型訪問。如將主鍵置於where列表中,MySQL就能將該查詢轉換為一個常量,system是const類型的特例,當查詢的表只有一行的情況下,使用system

*NULL: MySQL在優化過程中分解語句,執行時甚至不用訪問表或索引,例如從一個索引列裡選取最小值可以通過單獨索引查找完成。

五、 possible_keys,可能使用的索引。

六、key,實際使用的索引

七、key_len,索引中使用的字節數,可通過該列計算查詢中使用的索引的長度

八、ref,列與索引的比較,表示上述表的連接匹配條件

九、rows,估算出結果集行數

十、Extra,MySQL解決查詢的詳細信息

*Using where:不用讀取表中所有信息,僅通過索引就可以獲取所需數據

*Using temporary:表示MySQL需要使用臨時表來存儲結果集,group by ; order by

*Using filesort:包含 order by ,而且無法利用索引完成的排序操作稱為“文件排序”

*Using join buffer:該值強調了在獲取連接條件時沒有使用索引,並且需要連接緩衝區來存儲中間結果。

*Impossible where:這個值強調了where語句會導致沒有符合條件的行。

*Select tables optimized away:這個值意味著僅通過使用索引,優化器可能僅從聚合函數結果中返回一行

*No tables used:Query語句中使用from dual 或不含任何from子句

以上就是對EXPLAIN工具的一個介紹,瞭解了這個工具後,我們結合這個執行工具,來看一看哪些情況會導致這個索引失效!

第一種情況:針對聯合索引,是否遵循最左匹配原則;

我們user_name,user_password,mobile建立一個聯合索引,如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

聯合索引其實是建立了三個索引,也就是user_name的索引,user_name,user_password的索引,user_name,user_password,mobile的索引,最左匹配原則的意思,是否在語句中使用了最左建立的索引,也就是user_name的索引,演示一下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

當我們把user_name的查詢條件去掉之後,會是什麼情況呢?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

我們會看到索引已經失效了,用的是全表掃描,違背了最左匹配的原則,那麼對於查詢語句select * from tb_user where user_password='admin66666' and user_name='admin66666' and mobile='1234566666'會用到索引嗎?答案如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

也是用到了聯合索引,這和你條件中寫的順序是沒有關係的!

第二種情況:在索引列上做了函數操作,會導致索引失效而導致全表掃描

我們先把那個聯合索引刪除掉,然後在user_name這一列上建立一個唯一索引:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

先不在索引列上做函數操作,執行計劃如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

很顯然使用了索引,那麼索引列進行函數操作呢?例如做一個字符拼接的操作:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

第三種情況:語句中like查詢是以%開頭,索引會失效變成全表掃描,覆蓋索引。

示例如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

如果模糊查詢不是以%開頭的,那麼也是可以用到索引的:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

第四種情況:使用is not null 會導致無法使用索引

示例如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

第五種情況:查詢語句中,如果條件中有or,即使其中有條件帶索引也不會使用。要想使用or,又想讓索引生效,只能將or條件中的每個列都加上索引

"
MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

在我們使用MySQL的過程中,隨著數據量越來越大,查詢顯得有些吃力,這時候就要針對查詢就行優化,針對查詢優化,通過給字段添加索引可以提高數據的讀取速度,提高項目的併發能力和抗壓能力。在上一篇我們講了給數據庫中的表添加索引,來提高它的查詢速度,但是會有另外一種情況出現,那就是我們給表中字段加了索引,但是查詢的時候依舊很慢,沒有什麼變化,這時就是因為建立的索引失效了,今天就來講一講索引失效的情況!

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於查看索引是否失效,MySQL數據庫針對每一條SQL語句,提供了一個查看它的執行計劃的工具,叫做EXPLAIN,咱們先來了解一下這個工具。首先說一下接下來用到的表,創建的表結構為:

CREATE TABLE `tb_user` (
`id` BIGINT (20),
`user_name` VARCHAR (200),
`user_password` VARCHAR (200),
`birth` DATETIME ,
`sex` CHAR (4),
\t\t\t\t `age` int(8),
`email` VARCHAR (200),
`mobile` VARCHAR (200),
`create_date` DATETIME ,
`update_date` DATETIME ,
`description` VARCHAR (800)
) ENGINE=INNODB;

創建一個存儲函數,向裡面插入一百萬條數據:

DELIMITER $$
CREATE
PROCEDURE insert_tb_user()
BEGIN
DECLARE i INT;
SET i=0;
WHILE i>=0 && i<= 1000000 DO
INSERT INTO tb_user
(`id`, `user_name`, `user_password`, `birth`, `sex`, `age`, `email`, `mobile`, `create_date`, `update_date`, `description`) VALUES
(i,concat('admin',i),concat('admin',i),NOW(),'M',i,'[email protected]',concat('12345',i),NOW(),NOW(),concat('超級管理員',i));
SET i=i + 1;
END WHILE;

END$$
DELIMITER ;
-- 執行存儲函數
call insert_tb_user()

生成的表數據如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

利用這個表,我們來介紹一下執行計劃和索引失效的情況。

首先來看一下執行計劃的結果是什麼樣的,執行計劃的查看,就是在查詢語句的前面加上EXPLAIN關鍵字就可以了:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於這些字段的意思,咱們一一來解釋:

一、 id,SELECT識別符。

*id相同時,執行順序由上至下

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

二、select_type,查詢中每個select子句的類型

*SIMPLE(簡單SELECT,不使用UNION或子查詢等)

*PRIMARY(子查詢中最外層查詢)

*UNION(UNION中的第二個或後面的SELECT語句)

*DEPENDENT UNION(UNION中的第二個或後面的SELECT語句)

*UNION RESULT(UNION的結果,union語句中第二個select開始後面所有select)

*SUBQUERY(子查詢中的第一個SELECT,結果不依賴於外部查詢)

*DEPENDENT SUBQUERY(子查詢中的第一個SELECT,依賴於外部查詢)

* DERIVED(派生表的SELECT, FROM子句的子查詢)

* UNCACHEABLE SUBQUERY(一個子查詢的結果不能被緩存,必須重新評估外鏈接的第一行)

三、 table,顯示這一步所訪問數據庫中表名稱。

四、type,對錶訪問方式

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

*index: Full Index Scan,index與ALL區別為index類型只遍歷索引樹

*range:只檢索給定範圍的行,使用一個索引來選擇行

*ref: 表示上述表的連接匹配條件,即哪些列或常量被用於查找索引列上的值

*eq_ref: 類似ref,區別就在使用的索引是唯一索引,對於每個索引鍵值,表中只有一條記錄匹配,簡單來說,就是多表連接中使用primary key或者 unique key作為關聯條件

*const、system: 當MySQL對查詢某部分進行優化,並轉換為一個常量時,使用這些類型訪問。如將主鍵置於where列表中,MySQL就能將該查詢轉換為一個常量,system是const類型的特例,當查詢的表只有一行的情況下,使用system

*NULL: MySQL在優化過程中分解語句,執行時甚至不用訪問表或索引,例如從一個索引列裡選取最小值可以通過單獨索引查找完成。

五、 possible_keys,可能使用的索引。

六、key,實際使用的索引

七、key_len,索引中使用的字節數,可通過該列計算查詢中使用的索引的長度

八、ref,列與索引的比較,表示上述表的連接匹配條件

九、rows,估算出結果集行數

十、Extra,MySQL解決查詢的詳細信息

*Using where:不用讀取表中所有信息,僅通過索引就可以獲取所需數據

*Using temporary:表示MySQL需要使用臨時表來存儲結果集,group by ; order by

*Using filesort:包含 order by ,而且無法利用索引完成的排序操作稱為“文件排序”

*Using join buffer:該值強調了在獲取連接條件時沒有使用索引,並且需要連接緩衝區來存儲中間結果。

*Impossible where:這個值強調了where語句會導致沒有符合條件的行。

*Select tables optimized away:這個值意味著僅通過使用索引,優化器可能僅從聚合函數結果中返回一行

*No tables used:Query語句中使用from dual 或不含任何from子句

以上就是對EXPLAIN工具的一個介紹,瞭解了這個工具後,我們結合這個執行工具,來看一看哪些情況會導致這個索引失效!

第一種情況:針對聯合索引,是否遵循最左匹配原則;

我們user_name,user_password,mobile建立一個聯合索引,如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

聯合索引其實是建立了三個索引,也就是user_name的索引,user_name,user_password的索引,user_name,user_password,mobile的索引,最左匹配原則的意思,是否在語句中使用了最左建立的索引,也就是user_name的索引,演示一下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

當我們把user_name的查詢條件去掉之後,會是什麼情況呢?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

我們會看到索引已經失效了,用的是全表掃描,違背了最左匹配的原則,那麼對於查詢語句select * from tb_user where user_password='admin66666' and user_name='admin66666' and mobile='1234566666'會用到索引嗎?答案如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

也是用到了聯合索引,這和你條件中寫的順序是沒有關係的!

第二種情況:在索引列上做了函數操作,會導致索引失效而導致全表掃描

我們先把那個聯合索引刪除掉,然後在user_name這一列上建立一個唯一索引:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

先不在索引列上做函數操作,執行計劃如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

很顯然使用了索引,那麼索引列進行函數操作呢?例如做一個字符拼接的操作:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

第三種情況:語句中like查詢是以%開頭,索引會失效變成全表掃描,覆蓋索引。

示例如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

如果模糊查詢不是以%開頭的,那麼也是可以用到索引的:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

第四種情況:使用is not null 會導致無法使用索引

示例如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

第五種情況:查詢語句中,如果條件中有or,即使其中有條件帶索引也不會使用。要想使用or,又想讓索引生效,只能將or條件中的每個列都加上索引

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

上面的sql語句是可以用到索引的,當我們把and換成or時,就會變成全表掃描:

"
MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

在我們使用MySQL的過程中,隨著數據量越來越大,查詢顯得有些吃力,這時候就要針對查詢就行優化,針對查詢優化,通過給字段添加索引可以提高數據的讀取速度,提高項目的併發能力和抗壓能力。在上一篇我們講了給數據庫中的表添加索引,來提高它的查詢速度,但是會有另外一種情況出現,那就是我們給表中字段加了索引,但是查詢的時候依舊很慢,沒有什麼變化,這時就是因為建立的索引失效了,今天就來講一講索引失效的情況!

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於查看索引是否失效,MySQL數據庫針對每一條SQL語句,提供了一個查看它的執行計劃的工具,叫做EXPLAIN,咱們先來了解一下這個工具。首先說一下接下來用到的表,創建的表結構為:

CREATE TABLE `tb_user` (
`id` BIGINT (20),
`user_name` VARCHAR (200),
`user_password` VARCHAR (200),
`birth` DATETIME ,
`sex` CHAR (4),
\t\t\t\t `age` int(8),
`email` VARCHAR (200),
`mobile` VARCHAR (200),
`create_date` DATETIME ,
`update_date` DATETIME ,
`description` VARCHAR (800)
) ENGINE=INNODB;

創建一個存儲函數,向裡面插入一百萬條數據:

DELIMITER $$
CREATE
PROCEDURE insert_tb_user()
BEGIN
DECLARE i INT;
SET i=0;
WHILE i>=0 && i<= 1000000 DO
INSERT INTO tb_user
(`id`, `user_name`, `user_password`, `birth`, `sex`, `age`, `email`, `mobile`, `create_date`, `update_date`, `description`) VALUES
(i,concat('admin',i),concat('admin',i),NOW(),'M',i,'[email protected]',concat('12345',i),NOW(),NOW(),concat('超級管理員',i));
SET i=i + 1;
END WHILE;

END$$
DELIMITER ;
-- 執行存儲函數
call insert_tb_user()

生成的表數據如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

利用這個表,我們來介紹一下執行計劃和索引失效的情況。

首先來看一下執行計劃的結果是什麼樣的,執行計劃的查看,就是在查詢語句的前面加上EXPLAIN關鍵字就可以了:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於這些字段的意思,咱們一一來解釋:

一、 id,SELECT識別符。

*id相同時,執行順序由上至下

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

二、select_type,查詢中每個select子句的類型

*SIMPLE(簡單SELECT,不使用UNION或子查詢等)

*PRIMARY(子查詢中最外層查詢)

*UNION(UNION中的第二個或後面的SELECT語句)

*DEPENDENT UNION(UNION中的第二個或後面的SELECT語句)

*UNION RESULT(UNION的結果,union語句中第二個select開始後面所有select)

*SUBQUERY(子查詢中的第一個SELECT,結果不依賴於外部查詢)

*DEPENDENT SUBQUERY(子查詢中的第一個SELECT,依賴於外部查詢)

* DERIVED(派生表的SELECT, FROM子句的子查詢)

* UNCACHEABLE SUBQUERY(一個子查詢的結果不能被緩存,必須重新評估外鏈接的第一行)

三、 table,顯示這一步所訪問數據庫中表名稱。

四、type,對錶訪問方式

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

*index: Full Index Scan,index與ALL區別為index類型只遍歷索引樹

*range:只檢索給定範圍的行,使用一個索引來選擇行

*ref: 表示上述表的連接匹配條件,即哪些列或常量被用於查找索引列上的值

*eq_ref: 類似ref,區別就在使用的索引是唯一索引,對於每個索引鍵值,表中只有一條記錄匹配,簡單來說,就是多表連接中使用primary key或者 unique key作為關聯條件

*const、system: 當MySQL對查詢某部分進行優化,並轉換為一個常量時,使用這些類型訪問。如將主鍵置於where列表中,MySQL就能將該查詢轉換為一個常量,system是const類型的特例,當查詢的表只有一行的情況下,使用system

*NULL: MySQL在優化過程中分解語句,執行時甚至不用訪問表或索引,例如從一個索引列裡選取最小值可以通過單獨索引查找完成。

五、 possible_keys,可能使用的索引。

六、key,實際使用的索引

七、key_len,索引中使用的字節數,可通過該列計算查詢中使用的索引的長度

八、ref,列與索引的比較,表示上述表的連接匹配條件

九、rows,估算出結果集行數

十、Extra,MySQL解決查詢的詳細信息

*Using where:不用讀取表中所有信息,僅通過索引就可以獲取所需數據

*Using temporary:表示MySQL需要使用臨時表來存儲結果集,group by ; order by

*Using filesort:包含 order by ,而且無法利用索引完成的排序操作稱為“文件排序”

*Using join buffer:該值強調了在獲取連接條件時沒有使用索引,並且需要連接緩衝區來存儲中間結果。

*Impossible where:這個值強調了where語句會導致沒有符合條件的行。

*Select tables optimized away:這個值意味著僅通過使用索引,優化器可能僅從聚合函數結果中返回一行

*No tables used:Query語句中使用from dual 或不含任何from子句

以上就是對EXPLAIN工具的一個介紹,瞭解了這個工具後,我們結合這個執行工具,來看一看哪些情況會導致這個索引失效!

第一種情況:針對聯合索引,是否遵循最左匹配原則;

我們user_name,user_password,mobile建立一個聯合索引,如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

聯合索引其實是建立了三個索引,也就是user_name的索引,user_name,user_password的索引,user_name,user_password,mobile的索引,最左匹配原則的意思,是否在語句中使用了最左建立的索引,也就是user_name的索引,演示一下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

當我們把user_name的查詢條件去掉之後,會是什麼情況呢?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

我們會看到索引已經失效了,用的是全表掃描,違背了最左匹配的原則,那麼對於查詢語句select * from tb_user where user_password='admin66666' and user_name='admin66666' and mobile='1234566666'會用到索引嗎?答案如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

也是用到了聯合索引,這和你條件中寫的順序是沒有關係的!

第二種情況:在索引列上做了函數操作,會導致索引失效而導致全表掃描

我們先把那個聯合索引刪除掉,然後在user_name這一列上建立一個唯一索引:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

先不在索引列上做函數操作,執行計劃如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

很顯然使用了索引,那麼索引列進行函數操作呢?例如做一個字符拼接的操作:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

第三種情況:語句中like查詢是以%開頭,索引會失效變成全表掃描,覆蓋索引。

示例如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

如果模糊查詢不是以%開頭的,那麼也是可以用到索引的:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

第四種情況:使用is not null 會導致無法使用索引

示例如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

第五種情況:查詢語句中,如果條件中有or,即使其中有條件帶索引也不會使用。要想使用or,又想讓索引生效,只能將or條件中的每個列都加上索引

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

上面的sql語句是可以用到索引的,當我們把and換成or時,就會變成全表掃描:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

這時我們對mobile也加上索引,這條sql語句也就會使用上索引:

"
MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

在我們使用MySQL的過程中,隨著數據量越來越大,查詢顯得有些吃力,這時候就要針對查詢就行優化,針對查詢優化,通過給字段添加索引可以提高數據的讀取速度,提高項目的併發能力和抗壓能力。在上一篇我們講了給數據庫中的表添加索引,來提高它的查詢速度,但是會有另外一種情況出現,那就是我們給表中字段加了索引,但是查詢的時候依舊很慢,沒有什麼變化,這時就是因為建立的索引失效了,今天就來講一講索引失效的情況!

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於查看索引是否失效,MySQL數據庫針對每一條SQL語句,提供了一個查看它的執行計劃的工具,叫做EXPLAIN,咱們先來了解一下這個工具。首先說一下接下來用到的表,創建的表結構為:

CREATE TABLE `tb_user` (
`id` BIGINT (20),
`user_name` VARCHAR (200),
`user_password` VARCHAR (200),
`birth` DATETIME ,
`sex` CHAR (4),
\t\t\t\t `age` int(8),
`email` VARCHAR (200),
`mobile` VARCHAR (200),
`create_date` DATETIME ,
`update_date` DATETIME ,
`description` VARCHAR (800)
) ENGINE=INNODB;

創建一個存儲函數,向裡面插入一百萬條數據:

DELIMITER $$
CREATE
PROCEDURE insert_tb_user()
BEGIN
DECLARE i INT;
SET i=0;
WHILE i>=0 && i<= 1000000 DO
INSERT INTO tb_user
(`id`, `user_name`, `user_password`, `birth`, `sex`, `age`, `email`, `mobile`, `create_date`, `update_date`, `description`) VALUES
(i,concat('admin',i),concat('admin',i),NOW(),'M',i,'[email protected]',concat('12345',i),NOW(),NOW(),concat('超級管理員',i));
SET i=i + 1;
END WHILE;

END$$
DELIMITER ;
-- 執行存儲函數
call insert_tb_user()

生成的表數據如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

利用這個表,我們來介紹一下執行計劃和索引失效的情況。

首先來看一下執行計劃的結果是什麼樣的,執行計劃的查看,就是在查詢語句的前面加上EXPLAIN關鍵字就可以了:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於這些字段的意思,咱們一一來解釋:

一、 id,SELECT識別符。

*id相同時,執行順序由上至下

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

二、select_type,查詢中每個select子句的類型

*SIMPLE(簡單SELECT,不使用UNION或子查詢等)

*PRIMARY(子查詢中最外層查詢)

*UNION(UNION中的第二個或後面的SELECT語句)

*DEPENDENT UNION(UNION中的第二個或後面的SELECT語句)

*UNION RESULT(UNION的結果,union語句中第二個select開始後面所有select)

*SUBQUERY(子查詢中的第一個SELECT,結果不依賴於外部查詢)

*DEPENDENT SUBQUERY(子查詢中的第一個SELECT,依賴於外部查詢)

* DERIVED(派生表的SELECT, FROM子句的子查詢)

* UNCACHEABLE SUBQUERY(一個子查詢的結果不能被緩存,必須重新評估外鏈接的第一行)

三、 table,顯示這一步所訪問數據庫中表名稱。

四、type,對錶訪問方式

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

*index: Full Index Scan,index與ALL區別為index類型只遍歷索引樹

*range:只檢索給定範圍的行,使用一個索引來選擇行

*ref: 表示上述表的連接匹配條件,即哪些列或常量被用於查找索引列上的值

*eq_ref: 類似ref,區別就在使用的索引是唯一索引,對於每個索引鍵值,表中只有一條記錄匹配,簡單來說,就是多表連接中使用primary key或者 unique key作為關聯條件

*const、system: 當MySQL對查詢某部分進行優化,並轉換為一個常量時,使用這些類型訪問。如將主鍵置於where列表中,MySQL就能將該查詢轉換為一個常量,system是const類型的特例,當查詢的表只有一行的情況下,使用system

*NULL: MySQL在優化過程中分解語句,執行時甚至不用訪問表或索引,例如從一個索引列裡選取最小值可以通過單獨索引查找完成。

五、 possible_keys,可能使用的索引。

六、key,實際使用的索引

七、key_len,索引中使用的字節數,可通過該列計算查詢中使用的索引的長度

八、ref,列與索引的比較,表示上述表的連接匹配條件

九、rows,估算出結果集行數

十、Extra,MySQL解決查詢的詳細信息

*Using where:不用讀取表中所有信息,僅通過索引就可以獲取所需數據

*Using temporary:表示MySQL需要使用臨時表來存儲結果集,group by ; order by

*Using filesort:包含 order by ,而且無法利用索引完成的排序操作稱為“文件排序”

*Using join buffer:該值強調了在獲取連接條件時沒有使用索引,並且需要連接緩衝區來存儲中間結果。

*Impossible where:這個值強調了where語句會導致沒有符合條件的行。

*Select tables optimized away:這個值意味著僅通過使用索引,優化器可能僅從聚合函數結果中返回一行

*No tables used:Query語句中使用from dual 或不含任何from子句

以上就是對EXPLAIN工具的一個介紹,瞭解了這個工具後,我們結合這個執行工具,來看一看哪些情況會導致這個索引失效!

第一種情況:針對聯合索引,是否遵循最左匹配原則;

我們user_name,user_password,mobile建立一個聯合索引,如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

聯合索引其實是建立了三個索引,也就是user_name的索引,user_name,user_password的索引,user_name,user_password,mobile的索引,最左匹配原則的意思,是否在語句中使用了最左建立的索引,也就是user_name的索引,演示一下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

當我們把user_name的查詢條件去掉之後,會是什麼情況呢?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

我們會看到索引已經失效了,用的是全表掃描,違背了最左匹配的原則,那麼對於查詢語句select * from tb_user where user_password='admin66666' and user_name='admin66666' and mobile='1234566666'會用到索引嗎?答案如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

也是用到了聯合索引,這和你條件中寫的順序是沒有關係的!

第二種情況:在索引列上做了函數操作,會導致索引失效而導致全表掃描

我們先把那個聯合索引刪除掉,然後在user_name這一列上建立一個唯一索引:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

先不在索引列上做函數操作,執行計劃如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

很顯然使用了索引,那麼索引列進行函數操作呢?例如做一個字符拼接的操作:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

第三種情況:語句中like查詢是以%開頭,索引會失效變成全表掃描,覆蓋索引。

示例如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

如果模糊查詢不是以%開頭的,那麼也是可以用到索引的:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

第四種情況:使用is not null 會導致無法使用索引

示例如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

第五種情況:查詢語句中,如果條件中有or,即使其中有條件帶索引也不會使用。要想使用or,又想讓索引生效,只能將or條件中的每個列都加上索引

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

上面的sql語句是可以用到索引的,當我們把and換成or時,就會變成全表掃描:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

這時我們對mobile也加上索引,這條sql語句也就會使用上索引:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

"
MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

在我們使用MySQL的過程中,隨著數據量越來越大,查詢顯得有些吃力,這時候就要針對查詢就行優化,針對查詢優化,通過給字段添加索引可以提高數據的讀取速度,提高項目的併發能力和抗壓能力。在上一篇我們講了給數據庫中的表添加索引,來提高它的查詢速度,但是會有另外一種情況出現,那就是我們給表中字段加了索引,但是查詢的時候依舊很慢,沒有什麼變化,這時就是因為建立的索引失效了,今天就來講一講索引失效的情況!

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於查看索引是否失效,MySQL數據庫針對每一條SQL語句,提供了一個查看它的執行計劃的工具,叫做EXPLAIN,咱們先來了解一下這個工具。首先說一下接下來用到的表,創建的表結構為:

CREATE TABLE `tb_user` (
`id` BIGINT (20),
`user_name` VARCHAR (200),
`user_password` VARCHAR (200),
`birth` DATETIME ,
`sex` CHAR (4),
\t\t\t\t `age` int(8),
`email` VARCHAR (200),
`mobile` VARCHAR (200),
`create_date` DATETIME ,
`update_date` DATETIME ,
`description` VARCHAR (800)
) ENGINE=INNODB;

創建一個存儲函數,向裡面插入一百萬條數據:

DELIMITER $$
CREATE
PROCEDURE insert_tb_user()
BEGIN
DECLARE i INT;
SET i=0;
WHILE i>=0 && i<= 1000000 DO
INSERT INTO tb_user
(`id`, `user_name`, `user_password`, `birth`, `sex`, `age`, `email`, `mobile`, `create_date`, `update_date`, `description`) VALUES
(i,concat('admin',i),concat('admin',i),NOW(),'M',i,'[email protected]',concat('12345',i),NOW(),NOW(),concat('超級管理員',i));
SET i=i + 1;
END WHILE;

END$$
DELIMITER ;
-- 執行存儲函數
call insert_tb_user()

生成的表數據如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

利用這個表,我們來介紹一下執行計劃和索引失效的情況。

首先來看一下執行計劃的結果是什麼樣的,執行計劃的查看,就是在查詢語句的前面加上EXPLAIN關鍵字就可以了:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於這些字段的意思,咱們一一來解釋:

一、 id,SELECT識別符。

*id相同時,執行順序由上至下

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

二、select_type,查詢中每個select子句的類型

*SIMPLE(簡單SELECT,不使用UNION或子查詢等)

*PRIMARY(子查詢中最外層查詢)

*UNION(UNION中的第二個或後面的SELECT語句)

*DEPENDENT UNION(UNION中的第二個或後面的SELECT語句)

*UNION RESULT(UNION的結果,union語句中第二個select開始後面所有select)

*SUBQUERY(子查詢中的第一個SELECT,結果不依賴於外部查詢)

*DEPENDENT SUBQUERY(子查詢中的第一個SELECT,依賴於外部查詢)

* DERIVED(派生表的SELECT, FROM子句的子查詢)

* UNCACHEABLE SUBQUERY(一個子查詢的結果不能被緩存,必須重新評估外鏈接的第一行)

三、 table,顯示這一步所訪問數據庫中表名稱。

四、type,對錶訪問方式

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

*index: Full Index Scan,index與ALL區別為index類型只遍歷索引樹

*range:只檢索給定範圍的行,使用一個索引來選擇行

*ref: 表示上述表的連接匹配條件,即哪些列或常量被用於查找索引列上的值

*eq_ref: 類似ref,區別就在使用的索引是唯一索引,對於每個索引鍵值,表中只有一條記錄匹配,簡單來說,就是多表連接中使用primary key或者 unique key作為關聯條件

*const、system: 當MySQL對查詢某部分進行優化,並轉換為一個常量時,使用這些類型訪問。如將主鍵置於where列表中,MySQL就能將該查詢轉換為一個常量,system是const類型的特例,當查詢的表只有一行的情況下,使用system

*NULL: MySQL在優化過程中分解語句,執行時甚至不用訪問表或索引,例如從一個索引列裡選取最小值可以通過單獨索引查找完成。

五、 possible_keys,可能使用的索引。

六、key,實際使用的索引

七、key_len,索引中使用的字節數,可通過該列計算查詢中使用的索引的長度

八、ref,列與索引的比較,表示上述表的連接匹配條件

九、rows,估算出結果集行數

十、Extra,MySQL解決查詢的詳細信息

*Using where:不用讀取表中所有信息,僅通過索引就可以獲取所需數據

*Using temporary:表示MySQL需要使用臨時表來存儲結果集,group by ; order by

*Using filesort:包含 order by ,而且無法利用索引完成的排序操作稱為“文件排序”

*Using join buffer:該值強調了在獲取連接條件時沒有使用索引,並且需要連接緩衝區來存儲中間結果。

*Impossible where:這個值強調了where語句會導致沒有符合條件的行。

*Select tables optimized away:這個值意味著僅通過使用索引,優化器可能僅從聚合函數結果中返回一行

*No tables used:Query語句中使用from dual 或不含任何from子句

以上就是對EXPLAIN工具的一個介紹,瞭解了這個工具後,我們結合這個執行工具,來看一看哪些情況會導致這個索引失效!

第一種情況:針對聯合索引,是否遵循最左匹配原則;

我們user_name,user_password,mobile建立一個聯合索引,如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

聯合索引其實是建立了三個索引,也就是user_name的索引,user_name,user_password的索引,user_name,user_password,mobile的索引,最左匹配原則的意思,是否在語句中使用了最左建立的索引,也就是user_name的索引,演示一下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

當我們把user_name的查詢條件去掉之後,會是什麼情況呢?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

我們會看到索引已經失效了,用的是全表掃描,違背了最左匹配的原則,那麼對於查詢語句select * from tb_user where user_password='admin66666' and user_name='admin66666' and mobile='1234566666'會用到索引嗎?答案如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

也是用到了聯合索引,這和你條件中寫的順序是沒有關係的!

第二種情況:在索引列上做了函數操作,會導致索引失效而導致全表掃描

我們先把那個聯合索引刪除掉,然後在user_name這一列上建立一個唯一索引:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

先不在索引列上做函數操作,執行計劃如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

很顯然使用了索引,那麼索引列進行函數操作呢?例如做一個字符拼接的操作:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

第三種情況:語句中like查詢是以%開頭,索引會失效變成全表掃描,覆蓋索引。

示例如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

如果模糊查詢不是以%開頭的,那麼也是可以用到索引的:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

第四種情況:使用is not null 會導致無法使用索引

示例如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

第五種情況:查詢語句中,如果條件中有or,即使其中有條件帶索引也不會使用。要想使用or,又想讓索引生效,只能將or條件中的每個列都加上索引

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

上面的sql語句是可以用到索引的,當我們把and換成or時,就會變成全表掃描:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

這時我們對mobile也加上索引,這條sql語句也就會使用上索引:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

第六種情況:使用不等於(!= 或者<>)的時候,無法使用索引,會導致索引失效

第七種情況:不能使用索引中範圍條件右邊的列,範圍之後索引失效。(< ,> between and)

這些情況就不在進行實際操作了,感興趣的朋友可以動手操作一下,也許隨著MySQL版本的更新迭代,對這些查詢語句進行內部優化,一些索引失效的情況就會消失。除了以上這些情況會導致索引失效,還有哪些情況會導致索引失效呢?

"
MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

在我們使用MySQL的過程中,隨著數據量越來越大,查詢顯得有些吃力,這時候就要針對查詢就行優化,針對查詢優化,通過給字段添加索引可以提高數據的讀取速度,提高項目的併發能力和抗壓能力。在上一篇我們講了給數據庫中的表添加索引,來提高它的查詢速度,但是會有另外一種情況出現,那就是我們給表中字段加了索引,但是查詢的時候依舊很慢,沒有什麼變化,這時就是因為建立的索引失效了,今天就來講一講索引失效的情況!

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於查看索引是否失效,MySQL數據庫針對每一條SQL語句,提供了一個查看它的執行計劃的工具,叫做EXPLAIN,咱們先來了解一下這個工具。首先說一下接下來用到的表,創建的表結構為:

CREATE TABLE `tb_user` (
`id` BIGINT (20),
`user_name` VARCHAR (200),
`user_password` VARCHAR (200),
`birth` DATETIME ,
`sex` CHAR (4),
\t\t\t\t `age` int(8),
`email` VARCHAR (200),
`mobile` VARCHAR (200),
`create_date` DATETIME ,
`update_date` DATETIME ,
`description` VARCHAR (800)
) ENGINE=INNODB;

創建一個存儲函數,向裡面插入一百萬條數據:

DELIMITER $$
CREATE
PROCEDURE insert_tb_user()
BEGIN
DECLARE i INT;
SET i=0;
WHILE i>=0 && i<= 1000000 DO
INSERT INTO tb_user
(`id`, `user_name`, `user_password`, `birth`, `sex`, `age`, `email`, `mobile`, `create_date`, `update_date`, `description`) VALUES
(i,concat('admin',i),concat('admin',i),NOW(),'M',i,'[email protected]',concat('12345',i),NOW(),NOW(),concat('超級管理員',i));
SET i=i + 1;
END WHILE;

END$$
DELIMITER ;
-- 執行存儲函數
call insert_tb_user()

生成的表數據如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

利用這個表,我們來介紹一下執行計劃和索引失效的情況。

首先來看一下執行計劃的結果是什麼樣的,執行計劃的查看,就是在查詢語句的前面加上EXPLAIN關鍵字就可以了:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

對於這些字段的意思,咱們一一來解釋:

一、 id,SELECT識別符。

*id相同時,執行順序由上至下

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

二、select_type,查詢中每個select子句的類型

*SIMPLE(簡單SELECT,不使用UNION或子查詢等)

*PRIMARY(子查詢中最外層查詢)

*UNION(UNION中的第二個或後面的SELECT語句)

*DEPENDENT UNION(UNION中的第二個或後面的SELECT語句)

*UNION RESULT(UNION的結果,union語句中第二個select開始後面所有select)

*SUBQUERY(子查詢中的第一個SELECT,結果不依賴於外部查詢)

*DEPENDENT SUBQUERY(子查詢中的第一個SELECT,依賴於外部查詢)

* DERIVED(派生表的SELECT, FROM子句的子查詢)

* UNCACHEABLE SUBQUERY(一個子查詢的結果不能被緩存,必須重新評估外鏈接的第一行)

三、 table,顯示這一步所訪問數據庫中表名稱。

四、type,對錶訪問方式

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

*index: Full Index Scan,index與ALL區別為index類型只遍歷索引樹

*range:只檢索給定範圍的行,使用一個索引來選擇行

*ref: 表示上述表的連接匹配條件,即哪些列或常量被用於查找索引列上的值

*eq_ref: 類似ref,區別就在使用的索引是唯一索引,對於每個索引鍵值,表中只有一條記錄匹配,簡單來說,就是多表連接中使用primary key或者 unique key作為關聯條件

*const、system: 當MySQL對查詢某部分進行優化,並轉換為一個常量時,使用這些類型訪問。如將主鍵置於where列表中,MySQL就能將該查詢轉換為一個常量,system是const類型的特例,當查詢的表只有一行的情況下,使用system

*NULL: MySQL在優化過程中分解語句,執行時甚至不用訪問表或索引,例如從一個索引列裡選取最小值可以通過單獨索引查找完成。

五、 possible_keys,可能使用的索引。

六、key,實際使用的索引

七、key_len,索引中使用的字節數,可通過該列計算查詢中使用的索引的長度

八、ref,列與索引的比較,表示上述表的連接匹配條件

九、rows,估算出結果集行數

十、Extra,MySQL解決查詢的詳細信息

*Using where:不用讀取表中所有信息,僅通過索引就可以獲取所需數據

*Using temporary:表示MySQL需要使用臨時表來存儲結果集,group by ; order by

*Using filesort:包含 order by ,而且無法利用索引完成的排序操作稱為“文件排序”

*Using join buffer:該值強調了在獲取連接條件時沒有使用索引,並且需要連接緩衝區來存儲中間結果。

*Impossible where:這個值強調了where語句會導致沒有符合條件的行。

*Select tables optimized away:這個值意味著僅通過使用索引,優化器可能僅從聚合函數結果中返回一行

*No tables used:Query語句中使用from dual 或不含任何from子句

以上就是對EXPLAIN工具的一個介紹,瞭解了這個工具後,我們結合這個執行工具,來看一看哪些情況會導致這個索引失效!

第一種情況:針對聯合索引,是否遵循最左匹配原則;

我們user_name,user_password,mobile建立一個聯合索引,如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

聯合索引其實是建立了三個索引,也就是user_name的索引,user_name,user_password的索引,user_name,user_password,mobile的索引,最左匹配原則的意思,是否在語句中使用了最左建立的索引,也就是user_name的索引,演示一下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

當我們把user_name的查詢條件去掉之後,會是什麼情況呢?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

我們會看到索引已經失效了,用的是全表掃描,違背了最左匹配的原則,那麼對於查詢語句select * from tb_user where user_password='admin66666' and user_name='admin66666' and mobile='1234566666'會用到索引嗎?答案如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

也是用到了聯合索引,這和你條件中寫的順序是沒有關係的!

第二種情況:在索引列上做了函數操作,會導致索引失效而導致全表掃描

我們先把那個聯合索引刪除掉,然後在user_name這一列上建立一個唯一索引:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

先不在索引列上做函數操作,執行計劃如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

很顯然使用了索引,那麼索引列進行函數操作呢?例如做一個字符拼接的操作:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

第三種情況:語句中like查詢是以%開頭,索引會失效變成全表掃描,覆蓋索引。

示例如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

如果模糊查詢不是以%開頭的,那麼也是可以用到索引的:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

第四種情況:使用is not null 會導致無法使用索引

示例如下:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

第五種情況:查詢語句中,如果條件中有or,即使其中有條件帶索引也不會使用。要想使用or,又想讓索引生效,只能將or條件中的每個列都加上索引

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

上面的sql語句是可以用到索引的,當我們把and換成or時,就會變成全表掃描:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

這時我們對mobile也加上索引,這條sql語句也就會使用上索引:

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

第六種情況:使用不等於(!= 或者<>)的時候,無法使用索引,會導致索引失效

第七種情況:不能使用索引中範圍條件右邊的列,範圍之後索引失效。(< ,> between and)

這些情況就不在進行實際操作了,感興趣的朋友可以動手操作一下,也許隨著MySQL版本的更新迭代,對這些查詢語句進行內部優化,一些索引失效的情況就會消失。除了以上這些情況會導致索引失效,還有哪些情況會導致索引失效呢?

MySQL索引失效和EXPLAIN工具:你建立的索引真的起到作用了嗎?

"

相關推薦

推薦中...