1. 程式人生 > 實用技巧 >導致MySQL索引失效的幾種常見寫法

導致MySQL索引失效的幾種常見寫法

資料準備

先準備一些資料,方便測試

建立表結構

CREATE TABLE USER(
  id INT(5) UNSIGNED NOT NULL AUTO_INCREMENT,
  create_time DATETIME NOT NULL,
  NAME VARCHAR(5) NOT NULL,
  age TINYINT(2) UNSIGNED ZEROFILL NOT NULL,
  sex CHAR(1) NOT NULL,
  mobile CHAR(12) NOT NULL DEFAULT '',
  address CHAR(120) DEFAULT NULL,
  height 
VARCHAR(10) DEFAULT NULL, PRIMARY KEY (id), KEY idx_createtime (create_time) USING BTREE, KEY idx_name_age_sex (NAME,sex,age) USING BTREE, KEY idx_height (height) USING BTREE, KEY idx_address (address) USING BTREE, KEY idx_age (age) USING BTREE ) ENGINE=INNODB AUTO_INCREMENT=261 DEFAULT CHARSET=
utf8; 新增資料 INSERT INTO test.user(id, create_time, name, age, sex, mobile, address, height`) VALUES (1, '2019-09-02 10:17:47', '冰峰', 22, '', '1', '陝西省咸陽市彬縣', '175'); INSERT INTO test.user(id, create_time, NAME, age, sex, mobile, address, height) VALUES (2, '2020-09-02 10:17:47', '松子', 13, '', '1', NULL, '
180'); INSERT INTO test.user(id, create_time, NAME, age, sex, mobile, address, height) VALUES (3, '2020-09-02 10:17:48', '蠶豆', 20, '', '1', NULL, '180'); INSERT INTO test.user(id, create_time, NAME, age, sex, mobile, address, height) VALUES (4, '2020-09-02 10:17:47', '冰峰', 20, '', '17765010977', '陝西省西安市', '155'); INSERT INTO test.user(id, create_time, NAME, age, sex, mobile, address, height) VALUES (255, '2020-09-02 10:17:47', '竹筍', 22, '', '我測試下可以儲存幾個中文', NULL, '180'); INSERT INTO test.user(id, create_time, NAME, age, sex, mobile, address, height) VALUES (256, '2020-09-03 10:17:47', '冰峰', 21, '', '', NULL, '167'); INSERT INTO test.user(id, create_time, NAME, age, sex, mobile, address, height) VALUES (257, '2020-09-02 10:17:47', '小紅', 20, '', '', NULL, '180'); INSERT INTO test.user(id, create_time, NAME, age, sex, mobile, address, height) VALUES (258, '2020-09-02 10:17:47', '小鵬', 20, '', '', NULL, '188'); INSERT INTO test.user(id, create_time, NAME, age, sex, mobile, address, height) VALUES (259, '2020-09-02 10:17:47', '張三', 20, '', '', NULL, '180'); INSERT INTO test.user(id, create_time, NAME, age, sex, mobile, address, height) VALUES (260, '2020-09-02 10:17:47', '李四', 22, '', '', NULL, '165');

導致索引失效

單個索引

1、使用!= 或者 <> 導致索引失效
SELECT * FROM user WHERE name != '冰峰';

可以通過分析SQL看到,type型別是ALL,掃描了10行資料,進行了全表掃描。<>也是同樣的結果。

2、型別不一致導致的索引失效

注意:設計表字段的時候,千萬、一定、必須要保持欄位型別的一致性,啥意思?比如user表的id是int自增,到了使用者的賬戶表user_id這個欄位,一定、必須也是int型別,千萬不要寫成varchar、char什麼的騷操作。

SELECT * FROM user WHERE height= 175;

可以通過分析SQL看到

上面這個索引失效是因為:這個SQL諸位一定要看清楚,height表字段型別是varchar,但是我查詢的時候使用了數字型別,因為這個中間存在一個隱式的型別轉換,所以就會導致索引失效,進行全表掃描。

對比一下

SELECT * FROM USER WHERE NAME = '張三' AND height = '175';

可以通過分析SQL看到

3、函式導致的索引失效

如果你對列進行了(+,-,*,/,!), 那麼都將不會走索引。

SELECT * FROM USER WHERE age - 1 = 20;

結果如下:

5、OR引起的索引失效(特殊情況下:即不是同一個索引字段)
SELECT * FROM user WHERE name = '張三' OR height = '175';

注意:OR導致索引是在特定情況下的,並不是所有的OR都是使索引失效,如果OR連線的是同一個欄位,那麼索引不會失效,反之索引失效

結果如下:

6、模糊搜尋導致的索引失效
SELECT * FROM USER WHERE NAME LIKE '%冰%';

結果如下

比較一下:

SELECT * FROM USER WHERE NAME LIKE '冰%';

7、NOT IN、NOT EXISTS導致索引失效
SELECT s.* FROM user s WHERE NOT EXISTS (SELECT * FROM user u WHERE u.name = s.name AND u.name = '冰峰')

結果如下:

SELECT * FROM user WHERE name NOT IN ('冰峰');

結果如下:

複合索引

注意 在測試複合索引時 要測試之前,刪除其他的單列索引。

1、最左匹配原則
EXPLAIN SELECT * FROM USER WHERE NAME = '冰峰' AND sex = '';

啥叫最左匹配原則,就是對於符合索引來說,它的一個索引的順序是從左往右依次進行比較的