MySQL中索引失效的常见场景与规避方法

下面是详细讲解 MySQL 中索引失效的常见场景与规避方法的完整攻略:

索引失效的原因

MySQL 中索引失效的原因有很多,这里我们列举其中一些常见的情况:

预测索引无效

预测索引的含义是:使用非索引列做条件,MySQL 仍然会对该列做全表扫描,而不是使用索引。例如下面这个表:

CREATE TABLE student (
  name VARCHAR(20),
  age INT,
  PRIMARY KEY (name)
);

如果我们要查询年龄为 18 的学生,但是只使用了 age 字段作为条件:

SELECT * FROM student WHERE age=18;

MySQL 会发现没有合适的索引可以使用,于是会做全表扫描。要避免这种情况,我们需要对 age 字段添加索引,这样查询语句就会变成:

SELECT * FROM student WHERE age=18 AND name IS NOT NULL;

这样 MySQL 就会使用 agename 两个字段的组合索引来处理查询请求。

不使用索引列

MySQL 在执行查询语句时,只有在查询条件中出现的列才会被使用到索引。例如下面这个表:

CREATE TABLE student (
  name VARCHAR(20),
  age INT,
  PRIMARY KEY (name)
);

如果我们要查询名字以 T 开头的学生,但是只使用了年龄作为条件:

SELECT * FROM student WHERE age=18;

这时 MySQL 会发现查询条件中没有 name 这个索引列,于是不使用索引,做全表扫描。要避免这种情况,需要对 name 字段添加索引,或者将 name 字段作为查询条件。

索引列使用函数或操作符

如果在查询语句中使用了函数或操作符对索引列进行处理,MySQL 会放弃使用索引。例如下面这个表:

CREATE TABLE student (
  name VARCHAR(20),
  age INT,
  PRIMARY KEY (name),
  INDEX age_index (age)
);

如果我们要查询年龄为 18 的学生,但是使用了函数对 age 字段进行处理:

SELECT * FROM student WHERE age/2=9;

这时 MySQL 会放弃使用 age_index 索引,而是做全表扫描。要解决这个问题,我们需要减少使用函数和操作符,或者对 age 字段进行计算并将运算结果写入另外一个列中,再使用这个新列来进行查询。

索引失效的规避方法

针对上述的情况,我提出一些规避方法,如下所示:

设计合适的索引

在设计数据表时,需要针对具体的查询语句来确定需要哪些索引。一般来说,需要为经常查询和排序的列添加索引。同时,需要避免创建过多的冗余索引,这会导致数据库性能下降。

避免使用函数和操作符

在查询语句中尽量避免使用函数和操作符。如果无法避免,可以考虑使用函数和操作符的逆运算来代替原有的函数和操作符。

善用 Explain

Explain 是 MySQL 中一个用于分析查询语句的工具,可以通过 Explain 分析查询语句的执行计划、索引使用情况等。通过分析 Explain 的输出结果,可以找到查询语句的性能瓶颈和优化方向。

适当调整 MySQL 参数

MySQL 中有很多参数可以配置,例如缓存大小、连接数、查询缓存等。适当调整这些参数可以提高 MySQL 的性能和稳定性。需要注意的是,不同的参数调整适用于不同的场景,需要谨慎评估。

示例说明

为了更好地理解索引失效的原因和规避方法,下面举两个实例进行说明。

实例一

假设有一个表 user,包含了用户 ID、用户名、性别等字段。我们要查询性别为女性的用户名以 W 开头的用户的 ID 和用户名两个字段。为了提高查询速度,我们向表中添加了一个联合索引:

ALTER TABLE user ADD INDEX `idx_gender_username` (`gender`, `username`(8));

然后我们执行了如下这个查询语句:

SELECT id, username FROM user WHERE gender='女' AND LEFT(username, 1)='W';

通过 Explain 分析发现,该查询使用了索引,但是对索引列 username 使用了函数 LEFT,导致索引失效。我们可以将查询语句修改为:

SELECT id, username FROM user WHERE gender='女' AND username LIKE 'W%';

这样就可以避免使用函数,索引得到了正确使用。

实例二

假设有一个表 article,包含了文章 ID、标题、作者、创建时间等字段。我们要查询创建日期为 2019-01-01 的文章标题以 A 开头的文章的 ID 和标题两个字段。为了提高查询速度,我们向表中添加了两个索引:

ALTER TABLE article ADD INDEX `idx_create_time` (`create_time`);
ALTER TABLE article ADD INDEX `idx_title` (`title`(8));

然后我们执行了如下这个查询语句:

SELECT id, title FROM article WHERE DATE(create_time)='2019-01-01' AND LEFT(title, 1)='A';

通过 Explain 分析发现,该查询没有使用索引,而是进行了全表扫描。这是因为查询语句中对 create_time 列使用了函数 DATE,导致索引失效。我们可以将查询语句修改为:

SELECT id, title FROM article WHERE create_time BETWEEN '2019-01-01 00:00:00' AND '2019-01-01 23:59:59' AND title LIKE 'A%';

这样就可以避免使用函数,而且使用了覆盖索引,稍微优化了查询性能。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:MySQL中索引失效的常见场景与规避方法 - Python技术站

(0)
上一篇 2023年5月22日
下一篇 2023年5月22日

相关文章

  • php日期转时间戳,指定日期转换成时间戳

    要将日期转换为时间戳,可以使用PHP中的strtotime()函数。 该函数将日期时间字符串转换为指定格式的Unix时间戳。以下是使用该函数将日期转换为时间戳的步骤: 步骤一:使用strtotime()函数将指定日期时间字符串转换为Unix时间戳。 步骤二:在获取到时间戳后,存储该值,以备以后使用。 下面我们分别来演示一下两个案例。 案例一:将当前日期时间转…

    database 2023年5月22日
    00
  • swoole+websocket+redis实现一对一聊天

    如同web端的QQ和微信一样,这是一个web端的聊天程序。 环境:linux(centos) + php7.2 + swoole扩展 + redis + mysql Redis 实现每个连接websocket的服务都唯一绑定一个用户。通过 用户账号 = websocket fd 存到redis中。 Mysql 实现离线消息池。如果一个用户不在线,则其他用户发…

    Redis 2023年4月11日
    00
  • SQL Server视图的讲解

    下面我将为你详细讲解“SQL Server视图的讲解”的完整攻略。 什么是视图? 视图是 SQL Server 数据库中的一个概念,是基于一个或多个表的查询创建的虚拟表,视图与物理表很相似,但是它并不实际存在于数据库中,只是一个逻辑表。 视图的作用 通过视图我们可以很方便的隐藏表中的某些列,或者过滤掉一些特定的记录,从而简化复杂的 SQL 查询,提高查询效率…

    database 2023年5月21日
    00
  • mysql如何分别按年/月/日/周分组统计数据详解

    当我们想从MySQL数据库中统计按年/月/日/周分组的数据时,我们可以使用MySQL中的GROUP BY语句来进行分组统计。在GROUP BY语句中,我们可以通过使用YEAR(), MONTH(), DAYOFMONTH()和WEEK()等MySQL内置函数来分别按照年、月、日和周进行分组统计。 具体的语法格式如下所示: SELECT YEAR(date_c…

    database 2023年5月22日
    00
  • 一文搞懂阿里云服务器部署Redis并整合Spring Boot

    下面就为您详细讲解“一文搞懂阿里云服务器部署Redis并整合Spring Boot”的完整攻略。 简介 Redis是一个开源的基于键值对存储的数据结构服务器,可以用作数据库、缓存和消息中间件。Spring Boot是一个快速开发框架,它提供了多种实用工具和插件,可以帮助开发者快速构建基于Spring的应用程序。本文将介绍如何在阿里云服务器上部署Redis,然…

    database 2023年5月22日
    00
  • php循环输出数据库内容的代码

    首先我们来讲解如何使用PHP循环输出数据库内容的代码。 准备工作 在开始编写代码之前,我们需要准备好以下事项: 一台安装了PHP和MySQL的Web服务器。 一个数据库,里面包含我们要输出的数据表。 一个用于连接数据库的PHP文件,例如 config.php。 连接数据库 在开始循环输出数据库内容之前,我们需要先连接数据库。可以使用如下代码来连接数据库: &…

    database 2023年5月21日
    00
  • spring-data-redis版本冲突引发的问题

    1.昨天在maven build项目中发现有个问题,如下所示 java.lang.NoSuchMethodError: org.springframework.data.repository.config.AnnotationRepositoryConfigurationSource.<init>(Lorg/springframework/cor…

    Redis 2023年4月12日
    00
  • Oracle数据库并行查询出错的解决方法

    下面我将详细讲解“Oracle数据库并行查询出错的解决方法”的完整攻略,过程中会包含两条示例说明。 标题:Oracle数据库并行查询出错的解决方法 问题描述 在Oracle数据库进行并行查询时,可能会遇到以下错误信息: ORA-12801: 并行查询的结果超过了服务器限制,您可以使用查询重写、分片或者重新设计查询来减少并行查询的结果量。 这个错误信息通常出现…

    database 2023年5月21日
    00
合作推广
合作推广
分享本页
返回顶部