首頁 > 軟體

MySQL索引命中與失效程式碼實現

2023-01-18 14:02:31

建立表

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` int(5) NOT NULL AUTO_INCREMENT COMMENT '使用者id',
  `username` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '使用者名稱',
  `password` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '使用者密碼',
  `create_essay` int(5) NOT NULL COMMENT '原創文章',
  `user_visited` int(10) NOT NULL COMMENT '被存取量',
  `user_rank` int(5) NOT NULL COMMENT '使用者排名',
  `perms` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `nickname` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '使用者暱稱',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 116856 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

// 建立組合索引
ALTER TABLE `user` ADD INDEX idx_username_password_user_rank (`username`,`password`,`user_rank`)

這裡有一個組合索引的最左匹配原則:MySQL最左匹配原則

檢視MySQL中索引是否命中可以使用explainh執行優化器來檢視

MySQL執行優化器

執行優化器,顧名思義,優化語句的,準確來說是優化查詢語句。其實就是在我們寫的select語句前加一個Explain關鍵字。

索引的命中與失效情況

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

建立一個組合索引

idx_username_password_user_rank(`username`,`password`,`user_rank`)
// 命中索引跟順序無關
explain SELECT * from `user` where username =  "liuxiangcheng" and password = "515239" and user_rank = 1
explain SELECT * from `user` where user_rank = 1 and username =  "liuxiangcheng" and password = "515239"  
explain SELECT * from `user` where user_rank = 1 and password = "515239" and username =  "liuxiangcheng"

結果:

第二種情況:去掉大哥,看看索引是否命中;

// 去掉大哥
explain SELECT * from `user` where password = "515239" and user_rank = 1

去掉大哥之後,索引失效,全表掃描。

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

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

刪除組合索引

drop index idx_username_password_user_rank on `user`

建立唯一索引

alter table `user` ADD UNIQUE key (`username`)

檢視索引

explain SELECT * from `user` where username= 'user110819'

explain SELECT * from `user` where concat(username,'')= 'user110819'

第四種情況:模糊查詢字首是以%開頭的,索引失效

explain SELECT * from `user` where username like '%user11081'

第五種情況:模糊查詢中字尾是以%,可以命中索引

explain SELECT * from `user` where username like 'user11081%'

第六種情況:使用is not null 會導致索引失效

explain SELECT * from `user` where username is not null

第六種情況:使用and時,其中有一個條件查詢帶有索引而另一個不帶索引,不會導致索引失效。而使用or時,如果條件查詢中其中一個不帶索引,導致索引失效,必須全部帶有索引。

and情況:

explain SELECT * from `user` where username = "liuxiangcheng" and password = "515239"

or情況:

explain SELECT * from `user` where username = "liuxiangcheng" or user_rank = 1

我們給user_rank加上索引

alter table `user` ADD index (`user_rank`)

再次查詢:

explain SELECT * from `user` where username = "liuxiangcheng" or user_rank = 1

第七種情況:使用不等於(!= 或者<>)的時候,會導致索引失效

explain SELECT * from `user` where   user_rank != 1

or 

explain SELECT * from `user` where   user_rank <> 1

 第八種情況:使用範圍查詢之後索引失效

explain SELECT * from `user` where user_rank >(<,>=,<=) 1

 第九種情況:隱式轉換可能會導致我們的索引失效

varchar型別,如果用int型別來查詢,索引失效

資料庫user表中我們的password是varchar型別

如果我們在條件查詢中使用整形來替代,那麼這個時候索引就會失效,where varchar = int 索引失效

// password is varchar type

explain SELECT * from `user` where password = 515239

explain SELECT * from `user` where password = '515239'

explain SELECT * from `user` where password = "515239"

如果是int型別,我們使用varchar來替代,索引命中

// user_rank is int type

explain SELECT * from `user` where user_rank = "1"

explain SELECT * from `user` where user_rank = '1'

explain SELECT * from `user` where user_rank = 1

總結隱式轉換

  1. 當操作符左右兩邊的資料型別不一致時,會發生隱式轉換
  2. 當 where 查詢操作符左邊為數值型別時發生了隱式轉換,但是索引會命中,對查詢效率影響不大,但還是不推薦這麼做
  3. 當 where 查詢操作符左邊為字元型別時發生了隱式轉換,這樣會導致索引失效,造成全表掃描。
  4. 字串轉換為數值型別時,非數位開頭的字串會轉化為0,以數位開頭的字串會擷取從第一個字元到第一個非數位內容為止的值為轉化結果。

總結

MySQL中索引失效的情況

1、組合索引中不遵循最左匹配原則,帶頭大哥不在,導致索引失效,全表掃描。
2、在索引列上做了函數操作,導致索引失效,全表掃描。
3、模糊查詢字首是以%開頭的,導致索引失效,全表掃描。
4、使用is not null 會導致索引失效。
5、使用or時,如果條件查詢中其中一個不帶索引,導致索引失效,全表掃描。
6、使用不等於(!= 或者<>)的時候,會導致索引失效。
7、使用範圍查詢(>、<、>=、<=)之後索引失效。
8、隱式轉換可能會導致我們的索引失效。

 檢視MySQL中索引是否命中可以使用explainh執行優化器來檢視。

到此這篇關於MySQL索引命中與失效程式碼實現的文章就介紹到這了,更多相關MySQL索引命中與失效內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com