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

yizhihongxing

下面是详细讲解 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日

相关文章

  • 浅谈JDK14性能管理工具之jmap和jhat

    浅谈JDK14性能管理工具之jmap和jhat 什么是jmap和jhat jmap和jhat是JDK自带的性能管理工具,用于诊断和分析Java应用程序的内存使用情况。 jmap能够生成Java堆转储快照,可以获取Java堆中各种对象的详细信息。 jhat能够解析jmap生成的堆转储文件,将其中的数据展示为易于理解的HTML格式,方便开发者分析和调试。 jma…

    database 2023年5月21日
    00
  • MySQL – change 和 modify 的区别

    表描述MySQL 中 change 和 modify 区别 更改列名 change: alter table 表名 change 旧列名 新列名 类型 只更改列属性 change: alter table 表名 列名 列名 类型 相同的列名要写两次. 更改列属性 modify: alter table 表名 列名 类型 区别:1)change 可以更改列名 …

    MySQL 2023年4月12日
    00
  • Mysql中DATEDIFF函数的基础语法及练习案例

    Mysql中DATEDIFF函数可以用来计算两个日期之间的天数差。它的基础语法如下: DATEDIFF(date1, date2) 其中,date1和date2是指需要计算天数差值的两个日期,可以是一个列名、常量或一个表达式。函数的返回值是两个日期之间的天数差。 下面是两个DATEDIFF函数的案例示例: 案例一:计算两个固定日期之间的天数差 例如,要计算2…

    database 2023年5月22日
    00
  • linux下安装Squid代理的详细配置教程

    Linux下安装Squid代理的详细配置教程 前置条件 在进行Squid的安装及配置之前,需要确保满足以下条件: 系统为Linux操作系统 已经安装了GCC编译器和make工具 已经安装并配置好了yum或apt等包管理工具,以便于安装所需的软件包 安装Squid 使用包管理工具安装Squid: 对于CentOS系统: bash yum install squ…

    database 2023年5月22日
    00
  • SQL中Truncate的用法

    当需要清空表并且重置自动递增ID时,我们可以使用SQL中的Truncate命令。Truncate与DELETE操作非常相似,但是具有更高的效率。因为它不会记录删除行的操作日志,并且仅将表截断到指定的位置,因此它会更快地执行表清空操作。 语法 TRUNCATE TABLE table_name; 在这个语法中,table_name是要清空的表名。 示例 1 如…

    database 2023年5月21日
    00
  • MySQL 数据库常用命令 简单超级实用版

    MySQL 数据库常用命令 简单超级实用版 MySQL是一个常用的关系型数据库管理系统,下面列举出了一些MySQL数据库常用命令,让你更加了解MySQL。 登陆/退出 MySQL 连接到本地 MySQL 服务器: mysql -u username -p 其中,username是你的MySQL登陆名,-p表示需要输入密码。 连接到远程 MySQL 服务器: …

    database 2023年5月22日
    00
  • 开源MySQL高效数据仓库解决方案:Infobright详细介绍

    开源MySQL高效数据仓库解决方案:Infobright详细介绍 Infobright是一个开源的数据仓库解决方案,用于处理大数据情境下的OLAP查询,由于其出色的性能,得到不少公司的青睐。本文从Infobright的架构、优缺点、特点、优化路径等多个方面进行详细介绍,旨在使读者对Infobright有一个全面深入的了解。以下是Infobright的完整攻略…

    database 2023年5月19日
    00
  • 解决JDBC连接Mysql长时间无动作连接失效的问题

    解决JDBC连接Mysql长时间无动作连接失效的问题,可以通过以下步骤进行: 1. 配置连接参数 在JDBC程序中,通过配置连接参数可以控制连接的一些属性,如连接超时时间、读取超时时间等。这些参数的配置可以通过使用DriverManager.getConnection方法,以url的形式配置。例如: String url = "jdbc:mysql…

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