關於mysql優化部分,有很多網友說盡量避免使用is null, is not null,select * 等,會導致索引失效,性能降低?那是否一定收到影響呢?真的就不會使用索引了嗎?
本文的測試數據庫版本為5.7.18,不同版本得出的結果可能會有所不同:
本文測試的兩張表數據如下:
CREATE TABLE `t_user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) NOT NULL, `age` int(11) DEFAULT NULL, `sex` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; INSERT INTO `t_user` (`id`, `name`, `age`, `sex`) VALUES ('1', 'jemis', '20', '男'); INSERT INTO `t_user` (`id`, `name`, `age`, `sex`) VALUES ('2', 'fox', '20', '男'); INSERT INTO `t_user` (`id`, `name`, `age`, `sex`) VALUES ('3', 'tony', '20', '男'); CREATE UNIQUE INDEX indexName ON t_user(name(20));
一、索引字段不能為空的情況下:
測試select * 結合is null 和 is not null :
可以得出:
EXPLAIN select * from t_user where `name` is not null; 不使用索引;
EXPLAIN select * from t_user where `name` is null; 不使用索引;
查詢索引字段的情況下:
有以上可以得出查詢索引字段時:
EXPLAIN select name from t_user where `name` is not null; 使用索引
EXPLAIN select name from t_user where `name` is null; 不使用索引
select 索引字段加 非索引字段時:
可以得出:當select索引字段+其他字段時:
EXPLAIN select name,age from t_user where `name` is not null; 不使用索引
EXPLAIN select name,age from t_user where `name` is null; 不使用索引
由此可見,當索引字段不可以為null 時,只有使用is not null 並且返回的結果集中只包含索引字段時,才使用索引
二、當索引字段可以為null 時測試數據:
CREATE TABLE `t_user1` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) DEFAULT NULL, `age` int(11) DEFAULT NULL, `sex` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; INSERT INTO `springtest`.`t_user1` (`id`, `name`, `age`, `sex`) VALUES ('1', 'jemis', '20', '男'); INSERT INTO `springtest`.`t_user1` (`id`, `name`, `age`, `sex`) VALUES ('2', 'fox', '20', '男'); INSERT INTO `springtest`.`t_user1` (`id`, `name`, `age`, `sex`) VALUES ('3', 'tony', '20', '男'); CREATE UNIQUE INDEX indexName ON t_user1(name(20));
當索引字段可以為null,使用is null ,is not null:
當select * 時:
查詢語句select *:EXPLAIN select * from t_user1 where `name` is not null;; 不使用索引
EXPLAIN select * from t_user1 where `name` is null; 使用索引
select 索引字段:
select 索引字段的結論為:
EXPLAIN select name from t_user1 where `name` is not null; 使用索引
EXPLAIN select name from t_user1 where `name` is null; 使用索引
select 索引字段 + 非索引字段 為:
當select索引字段+其他字段時: EXPLAIN select name,age from t_user1 where `name` is not null;不使用索引,會導致索引失效
EXPLAIN select name,age from t_user1 where `name` is null; 使用索引
總結以上情形可知:1、當索引字段不可以為null 時,只有使用is not null 返回的結果集中只包含索引字段時,才使用索引
2、當索引字段可以為空時,使用 is null 不影響覆蓋索引,但是使用 is not null 只有完全返回索引字段時才會使用索引
最后附上本文的測試完整版sql以及結論:

CREATE TABLE `t_user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) NOT NULL, `age` int(11) DEFAULT NULL, `sex` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; INSERT INTO `springtest`.`t_user` (`id`, `name`, `age`, `sex`) VALUES ('1', 'jemis', '20', '男'); INSERT INTO `springtest`.`t_user` (`id`, `name`, `age`, `sex`) VALUES ('2', 'fox', '20', '男'); INSERT INTO `springtest`.`t_user` (`id`, `name`, `age`, `sex`) VALUES ('3', 'tony', '20', '男'); CREATE UNIQUE INDEX indexName ON t_user(name(20)); CREATE TABLE `t_user1` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) DEFAULT NULL, `age` int(11) DEFAULT NULL, `sex` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; INSERT INTO `springtest`.`t_user1` (`id`, `name`, `age`, `sex`) VALUES ('1', 'jemis', '20', '男'); INSERT INTO `springtest`.`t_user1` (`id`, `name`, `age`, `sex`) VALUES ('2', 'fox', '20', '男'); INSERT INTO `springtest`.`t_user1` (`id`, `name`, `age`, `sex`) VALUES ('3', 'tony', '20', '男'); CREATE UNIQUE INDEX indexName ON t_user1(name(20)); 當字段值可以為null,使用is null ,is not null, 查詢語句:EXPLAIN select * from t_user1 where `name` is not null;; 不使用索引 EXPLAIN select * from t_user1 where `name` is null; 使用索引 當不使用select * 時 : EXPLAIN select name from t_user1 where `name` is not null; 使用索引 EXPLAIN select name from t_user1 where `name` is null; 使用索引 當select索引字段+其他字段時: EXPLAIN select name,age from t_user1 where `name` is not null;不使用索引,會導致索引失效 EXPLAIN select name,age from t_user1 where `name` is null; 使用索引 從以上可以看出,當索引字段可以為空時,使用 is null 不影響覆蓋索引,但是使用 is not null 只有完全返回索引字段時才會使用索引 當字段值不能為null 時,EXPLAIN select * from t_user where `name` is not null; 不使用索引; EXPLAIN select * from t_user where `name` is null; 不使用索引; 當select索引字段 時 : EXPLAIN select name from t_user where `name` is not null; 使用索引 EXPLAIN select name from t_user where `name` is null; 不使用索引 當select索引字段+其他字段時: EXPLAIN select name,age from t_user where `name` is not null; 不使用索引 EXPLAIN select name,age from t_user where `name` is null; 不使用索引 由此可見,當索引字段不可以為null 時,只有使用is not null 返回的結果集中只包含索引字段時,才使用索引