这样写sql语句避免索引失效

       合理地对mysql数据表加上索引可以大大加快数据的访问效率,但也并不是在给表加上索引后就可以在sql中随心所欲地对加上索引的字段进行各种查询;如果sql的结构不当,会导致原本设置的索引失效。所以为避免采坑,写下此文,以做记录。以下用到的例子假设有这样一张表:

CREATE TABLE `user_info` (
  `id` bigint(32) NOT NULL,
  `name` varchar(32) DEFAULT NULL,
  `age` int(3) DEFAULT NULL,
  `address` varchar(32) DEFAULT NULL,
  `nick_name` varchar(32) DEFAULT NULL,
  `role_id` bigint(32) DEFAULT NULL,
  `create_time` date DEFAULT NULL,
  `update_time` date DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

一、尽量选择复合索引

        在对表创建索引时,如果可以使用复合索引,尽量使用复合索引而不是单列索引。理由如下,现创建的一个复合索引:

CREATE INDEX idx_name_age_status ON user(name, age, status);

        这里创建了一个名为idx_name_age_status的复合索引,实际上是创建了三个索引,分别是name, name + age, name + age + stauts,那么在使用name或name + age或name + age + stauts进行查询时,都可以使用到索引。而如果分别给三个字段创建索引,查询这张表时条件有这三个字段,数据库会选择一个最优的索引,而不会使用全部三个索引。

二、最左前缀法

        关系到复合索引时,注意最左前缀法,也就是查询的条件从索引的最左列开始,并且不跳过中间列,比如以下索引:

CREATE INDEX idx_name_age_status ON user(name, age, status);

        使用name或name + age或name + age + status进行查询能使索引生效,而使用单个查询条件age或status或者age + status 进行查询不会使索引生效,而使用name + stauts进行查询只会有name字段的索引生效。

三、复合索引中使用到范围查询右边的列索引不会生效

        在用到复合索引时,复合索引中使用到范围查询右边的列索引不会生效比如创建如下索引:

CREATE INDEX idx_name_age_status ON user(name, age, status);

        使用这三个字段作为查询条件,处于中间的age如果用到了范围查询,则status上的索引不会生效。

-- name + age + nick_name索引生效
SELECT * FROM user_info WHERE name = '张三' AND age = 22 AND nick_name = '三儿';
-- age用到了范围查询,仅name + age索引生效
SELECT * FROM user_info WHERE name = '张三' AND age > 22 AND nick_name = '三儿';

四、在索引列上进行运算操作后,索引将失效

        在索引列上进行运算操作后,索引将失效。比如有这样一个索引:

CREATE INDEX idx_age ON user_info(age);

        如果是where age = 22,这个索引会生效,但如果是age > 22,这个索引不会生效。

五、模糊匹配不生效的情况

        查询条件中的模糊条件,如果是以%开头,会不走索引,比如SELECT * FROM user_info WHERE name like '%三儿%'或SELECT * FROM user_info WHERE name like '%三儿',这样不会走索引;而SELECT * FROM user_info WHERE name like '三儿%',索引是有效的。

六、查询时字符串如果没加引号,索引失效

        查询时字符串如果没加引号,索引失效。在mysql中,假设有一个字段名称是name,类型为varchar,使用where name = 张三这种写法是错误语法,如果使用SELECT * FROM user_info WHERE name = 12虽可以进行查询的,但这样索引是不会生效的。

七、以or分隔的查询条件中,如果存在没有索引的列,分隔所关联的索引不会生效

        以or分隔的查询条件中,如果存在没有索引的列,分隔所关联的索引不会生效,比如给name列加上索引,以SELECT * FROM user_info WHERE name = '张三',这样写索引自然会生效,而如果有一列,比如nick_name上没有索引那么使用SELECT * FROM user_info WHERE name = '张三' OR nick_name = '三儿',name列上的索引也会失效。

八、尽量不使用SELECT *,最好只查询索引列

        尽量使用覆盖索引,也就是尽量只查询索引列,比如复合索引如下:

CREATE INDEX idx_name_age_status ON user(name, age, status);

       使用SELECT * FROM user_info WHERE name = '张三' AND age = 12 AND status = 1进行查询,索引自然会生效,但是效率是肯定不如SELECT name, age, status FROM user_info WHERE name = '张三' AND age = 12 AND status = 1。另外,在sql中尽量不要使用SELECT * FROM user_info这样的语法,而是尽量只查询需要的列,因为这样会影响查询的效率。

发布了48 篇原创文章 · 获赞 52 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/y506798278/article/details/103318372
今日推荐