1. 程式人生 > 其它 >mysql 資料庫索引在什麼場景下會失效?實戰篇

mysql 資料庫索引在什麼場景下會失效?實戰篇

 CREATE TABLE `user` (
   `id` int NOT NULL AUTO_INCREMENT,
   `code` varchar(20) COLLATE utf8mb4_bin DEFAULT NULL,
   `age` int DEFAULT '0',
   `name` varchar(30) COLLATE utf8mb4_bin DEFAULT NULL,
   `height` int DEFAULT '0',
   `address` varchar(30) COLLATE utf8mb4_bin DEFAULT NULL,
   PRIMARY KEY (`id`),
  
KEY `idx_code_age_name` (`code`,`age`,`name`), -- 建立 idx_code_age_name 索引 KEY `idx_height` (`height`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
 INSERT INTO sue.user (id, code, age, name, height,address) VALUES (1, '101', 21, '周星馳', 175,'香港');
-- INSERT INTO sue.user (id, code, age, name, height,address) VALUES (2, '102', 18, '周杰倫', 173,'臺灣');
INSERT INTO sue.user (id, code, age, name, height,address) VALUES (3, '203', 23, '蘇三', 174,'成都');
select version() as 'mysql版本號';

--  where 後面是主鍵,使用了主鍵索引
explain select * from user where id = 1;

-- 這5條sql中都有code欄位,它是索引欄位中的第一個欄位,也就是最左邊的欄位。只要有這個欄位在,該sql已經就能走索引。
explain select * from user where code =
'101'; explain select * from user where code = '101' and name = '周星馳' explain select * from user where code = '101' and age = 21 explain select * from user where code = '101' and age = 21 and name = '周星馳' explain select * from user where code = '101' and address = '香港' -- 不滿足最左匹配原則,沒有包含給定欄位最左邊的索引欄位,即欄位code。 explain select * from user where age =21 explain select * from user where name = '周星馳' explain select * from user where age = 21 and name = '周星馳' -- 使用select *查詢所有列的資料,大概率會查詢非索引列的資料,非索引列不會走索引,查詢效率非常低。 explain select * from user where name = '周星馳' -- select語句中的查詢列,都是索引列,那麼這些列被稱為覆蓋索引,查詢的相關欄位都能走索引. explain select code,name from user where name = '周星馳' explain select id,code,name from user where name = '周星馳' -- id欄位的主鍵索引,在有計算的情況下失效。id+1=2-->id = 2 explain select * from user where id+1=3 -- height 走普通索引 explain select * from user where height = 173 -- 在使用該函式 SUBSTR() 之後,走全表掃描,索引失效 explain select * from user where SUBSTR(height,1,3) = 173 -- 走聯合索引 idx_code_age_name ,查詢字元欄位時,用雙引號"和單引號'都可以。 explain select * from user where code = "101" -- code欄位的型別是varchar,而傳參的型別是int,兩種型別不同,索引失效。 explain select * from user where code = 101 -- 走普通索引:idx_height。int型別的引數,不管在查詢時加沒加引號,都能走索引。 explain select * from user where height = '175' -- 如果是int型別欄位作為查詢條件時,它會自動將該欄位的傳參進行隱式轉換,把字串轉換成int型別。 select 1+'1' -- 執行結果是2 -- 想拼接字串該怎麼辦?使用concat關鍵字。 select concat(1,'1') -- 執行結果是 11 -- 查出所有code是10開頭的使用者:%在引數右邊時走索引 explain select * from user where code like '10%' -- 查出所有code是1結尾的使用者:%在1左邊,code欄位索引失效 explain select * from user where code like '%1' -- 查出所有code包含1結尾的使用者:當like語句中的%,出現在查詢條件的左邊時,索引會失效。 select * from user where code like '%1%' -- 如果把兩個單獨建了索引的列,用來做列對比時索引會失效 explain select * from user where id = height -- myisam:如果使用了or關鍵字,那麼它前面和後面的欄位都要加索引,不然所有的索引都會失效。 -- innodb:在myisam的基礎上:資料量少不走索引,資料量大的前提下,比如100條資料查出符合條件的資料為少量,即:10條左右走索引,查出的資料為多量,即:70條左右則不走索引 explain select * from user where id = 2 or height= '173'; -- 走索引,結論如上 explain select * from user where height in (173,174,175,176); -- 內層走索引,外層結論如上 explain select * from user t1 where exists (select 1 from user t2 where t2.height=173 and t1.id=t2.id) -- 而普通索引欄位使用了not in關鍵字查詢資料範圍,索引會失效。結論如上 explain select * from user where height not in (173,174,175,176); -- 主鍵欄位中使用not in關鍵字查詢資料範圍,任然可以走索引。 explain select * from user where id not in (173,174,175,176); -- t1不走索引,t2走索引 explain select * from user t1 where not exists (select 1 from user t2 where t2.height=173 and t1.id=t2.id)