數據准備
先准備一些數據,方便測試
創建表結構 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 = '男';
啥叫最左匹配原則,就是對於符合索引來說,它的一個索引的順序是從左往右依次進行比較的