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日

相关文章

  • SQL中ALTER和UPDATE命令的区别

    ALTER和UPDATE都是SQL命令,但它们的作用不同。 ALTER命令 ALTER命令主要用于修改数据库表的结构,比如添加、删除或改变列的属性。 以下是ALTER命令的语法: ALTER TABLE table_name ADD COLUMN column_name data_type optional_arguments; 在这个语句中,ALTER T…

    database 2023年3月27日
    00
  • Spring线程池ThreadPoolExecutor配置并且得到任务执行的结果

    下面是Spring线程池ThreadPoolExecutor配置并且得到任务执行的结果的完整攻略。 概述 在多线程编程中,线程池是一个非常重要的概念。Spring 提供了一个 ThreadPoolExecutor 对象,可以方便地创建和管理线程池。在使用 ThreadPoolExecutor 的时候,需要通过配置一些参数来达到最优的效果。本攻略将详细介绍如何…

    database 2023年5月22日
    00
  • 浅谈mysql的中文乱码问题

    当我们在 MySQL 中存储或读取中文时,常常会遇到乱码问题。下面我将为大家介绍一些常见的中文乱码问题及解决方案。 问题一:插入中文数据时出现乱码 如果您在插入中文数据时出现了乱码,一般是由于以下原因: 字符集不匹配 数据库连接是二进制协议而不是文本协议 字符编码问题 其中,最常见的是字符集不匹配。MySQL 默认使用的字符集是 latin1,而大多数情况下…

    database 2023年5月22日
    00
  • mysql中datetime类型设置默认值方法

    当我们向数据库插入一条记录时,可能需要设置一些默认值,比如记录创建日期默认为当前时间。在 MySQL 中,我们可以使用 DATETIME 类型来存储日期和时间。那么如何为 DATETIME 类型设置默认值呢?下面提供两种方法。 方法一:使用 DEFAULT 关键字 在创建表时,使用 DEFAULT 关键字设置 DATETIME 字段的默认值。 CREATE …

    database 2023年5月22日
    00
  • MySQL数据库学习之去重与连接查询详解

    MySQL数据库学习之去重与连接查询详解 在使用MySQL时,去重和连接查询是两个常用的操作,本篇文章将详细讲解它们的使用方法。 去重查询 在MySQL中,使用DISTINCT关键字可以去重查询,示例代码如下: SELECT DISTINCT column1, column2, … FROM table_name; 其中,column1, column2…

    database 2023年5月22日
    00
  • SQL 使用SQL Server的PIVOT操作符创建交叉报表

    关于使用SQL Server的PIVOT操作符创建交叉报表的完整攻略,我会分成以下几个步骤来介绍: 确定数据源 定义PIVOT表达式 编写PIVOT查询语句 下面我就具体讲解一下这三个步骤。 1.确定数据源 在使用PIVOT操作符创建交叉报表之前,我们需要先确定一个数据源。碰巧我的电脑上有一个名叫“Sales”的数据库,它有一张名叫“Orders”的表,我们…

    database 2023年3月27日
    00
  • MySql数据库基础之子查询详解

    MySql数据库基础之子查询详解 什么是子查询 子查询(Subquery)也叫内部查询、嵌套查询,它指嵌套在其他 SQL 语句(例如 SELECT 语句)中的 SELECT 语句。子查询返回的结果会被用于外层查询,通常会用于 WHERE 或 HAVING 子句中。 子查询的语法 SELECT column1, column2, … FROM table_…

    database 2023年5月22日
    00
  • 你知道mysql哪些查询情况不走索引吗

    MySQL是一个关系型数据库,使用索引来提高数据查询的速度。然而,并不是所有的查询情况都能走索引。本文将详细讲解MySQL哪些查询情况会不走索引,并提供示例说明。 1.查询条件使用函数/运算符 如果查询条件使用了函数或运算符,MySQL将不会使用索引。因为MySQL无法在查询过程中运行函数或运算,因此会忽略索引,而全表扫描进行查询。 示例: SELECT *…

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