关于Mysql5.7及8.0版本索引失效情况汇总

关于MySQL 5.7及8.0版本索引失效情况汇总

索引失效的概念

在MySQL中,查询的速度与所涉及的数据量成正比,当数据量变大时,查询效率会明显下降,影响系统的性能。为了提高查询的效率,需要通过创建索引来实现。索引是一种数据结构,能够快速定位数据所在的位置,类似于书籍的目录,可以快速找到需要的内容。

但是,当数据量不断增加时,索引的维护成本也会随之增加,这时就需要注意索引失效的问题。索引失效指的是在数据查询时,MySQL无法使用索引来加速查询,而只能通过全表扫描来查找数据,导致查询效率显著下降。

导致索引失效的原因

  1. 对索引字段进行运算或函数操作

索引中存储的是数据的拷贝,因此对索引字段进行运算或函数操作会导致MySQL无法使用索引,例如:

SELECT * FROM users WHERE YEAR(register_time) = 2021;

由于对register_time字段进行了函数操作,MySQL无法使用该字段的索引,只能通过全表扫描来查找符合条件的数据。

  1. 对字段进行类型转换

MySQL会根据数据类型进行索引的创建,如果查询时对该字段进行类型转换,MySQL就无法使用索引,例如:

SELECT * FROM users WHERE CONVERT(id, CHAR) = '123';

由于将id字段转换为CHAR类型,MySQL无法使用该字段的索引,只能通过全表扫描来查找符合条件的数据。

  1. LIKE查询时,通配符在开头或两侧

LIKE查询时,如果通配符在开头或两侧,MySQL无法使用索引,例如:

SELECT * FROM users WHERE name LIKE '%张%';

由于通配符在两侧,MySQL无法使用name字段的索引,只能通过全表扫描来查找符合条件的数据。

  1. 查询条件中使用了OR

使用OR时,MySQL无法使用多个索引,也无法对多个索引进行合并,只能通过全表扫描来查找符合条件的数据,例如:

SELECT * FROM users WHERE province = '广东' OR city = '深圳';

MySQL无法使用provincecity字段的索引,只能通过全表扫描来查找符合条件的数据。

  1. 查询条件中使用了NOT

使用NOT时,MySQL无法使用索引,只能通过全表扫描来查找符合条件的数据,例如:

SELECT * FROM users WHERE NOT province = '广东';

MySQL无法使用province字段的索引,只能通过全表扫描来查找符合条件的数据。

更多导致索引失效的原因可以参考:《MySQL 行为和优化》第五章

索引失效示例

以下是两个导致索引失效的示例:

示例一:对索引字段进行运算或函数操作

假设有一张用户表users,表结构如下:

CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL,
  `password` varchar(50) NOT NULL,
  `register_time` datetime NOT NULL,
  PRIMARY KEY (`id`),
  KEY `register_time` (`register_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

此时如果查询register_time为2021年的所有用户,使用以下语句:

SELECT * FROM users WHERE YEAR(register_time) = 2021;

MySQL无法使用register_time字段的索引,只能通过全表扫描来查找符合条件的数据。

为了解决这个问题,可以使用以下语句:

SELECT * FROM users WHERE register_time BETWEEN '2021-01-01 00:00:00' AND '2021-12-31 23:59:59';

这样就可以使用register_time字段的索引来加速查询。

示例二:LIKE查询时,通配符在两侧

假设有一张用户表users,表结构如下:

CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL,
  `password` varchar(50) NOT NULL,
  `register_time` datetime NOT NULL,
  PRIMARY KEY (`id`),
  KEY `username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

此时如果查询username中包含的所有用户,使用以下语句:

SELECT * FROM users WHERE username LIKE '%张%';

MySQL无法使用username字段的索引,只能通过全表扫描来查找符合条件的数据。

为了解决这个问题,在设计表结构时,可以考虑将username字段使用全文索引来优化查询效率,使用以下语句创建全文索引:

CREATE FULLTEXT INDEX `username_fulltext` ON `users` (`username`);

然后使用以下语句来查询符合条件的数据:

SELECT * FROM users WHERE MATCH(username) AGAINST('张');

使用全文索引可以大幅提高查询效率。

总结

索引失效是MySQL中常见的问题,需要注意在查询时尽量避免上述导致索引失效的情况。如果无法避免,可以通过优化查询语句、重新设计表结构等方式来解决问题,从而提高查询效率,提升系统性能。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:关于Mysql5.7及8.0版本索引失效情况汇总 - Python技术站

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

相关文章

  • centos6.9 安装mysql8

    centos6.9 安装 mysql8   # 安装mysql8 1.下载https://cdn.mysql.com//Downloads/MySQL-8.0/mysql-8.0.16-2.el6.x86_64.rpm-bundle.tar 2.解压 tar -xvf mysql-8.0.16-2.el6.x86_64.rpm-bundle.tar rpm …

    MySQL 2023年4月12日
    00
  • 解决mysql ERROR 1045 (28000)– Access denied for user问题

    针对 mysql ERROR 1045 (28000)– Access denied for user 的问题,通常有以下三种解决办法: 1. 修改或重置 root 密码 步骤1:停止 MySQL 服务 在命令行输入以下命令停止 MySQL 服务: sudo systemctl stop mysql 步骤2:使用 -skip-grant-tables 参数…

    MySQL 2023年5月18日
    00
  • MySQL删除被其他表关联的数据库表

    MySQL中如果想要删除一个被其他表关联的表,需要先将关联该表的其他表中的数据删除,然后才能删除该表。具体步骤如下: 查找关联该表的其他表 可以通过以下SQL语句查询关联该表的其他表: SELECT TABLE_NAME, CONSTRAINT_NAME, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME FROM …

    MySQL 2023年3月9日
    00
  • MySQL优化方案参考

    MySQL优化方案参考攻略 1. 索引优化 1.1 索引分类 MySQL的索引分为主键索引和非主键索引。主键索引是基于表的主键定义的索引,非主键索引则是除主键外的普通索引。 1.2 索引设计原则 建立索引的字段应该尽量选择区分度高的字段,避免对字段的重复值建立索引。否则,索引失效的可能性比较大,建立的索引占用的磁盘空间也较大。 索引字段应该尽量选择长度小于等…

    MySQL 2023年5月19日
    00
  • 教你为MySQL数据库换挡加速

    教你为MySQL数据库换挡加速 为什么要进行MySQL数据库换挡? 当我们的网站或应用程序的数据库开始增加数据时,它的性能可能会受到影响。为了提高MySQL数据库的性能,我们需要为其换挡或优化。 常见的基本优化包括添加索引、优化查询语句等,但这些方法往往不能解决性能限制。在这种情况下,教你进行数据库换挡,可以是提高性能的另一种方法。 如何进行MySQL数据库…

    MySQL 2023年5月19日
    00
  • MySQL5.7中的sql_mode默认值带来的坑及解决方法

    MySQL5.7中的sql_mode默认值带来的坑及解决方法 在MySQL5.7版本中,sql_mode的默认值发生了变化,从之前的空值改成了ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE…

    MySQL 2023年5月18日
    00
  • 读SQL进阶教程笔记10_HAVING下

    1. 按照现在的SQL标准来说,HAVING子句是可以单独使用的 1.1. 就不能在SELECT子句里引用原来的表里的列了 1.1.1. 使用常量 1.1.2. 使用聚合函数 1.2. WHERE子句用来调查集合元素的性质,而HAVING子句用来调查集合本身的性质 2. 表不是文件,记录也没有顺序,所以SQL不进行排序 3. GROUP BY子句可以用来生成…

    MySQL 2023年4月17日
    00
  • docker-compose 安装 mysql:5.7.31

        目录 一.新建一个启动服务的目录 二.新建文件docker-compose.yml 三.新建角本文件 init-mysql.sh 四.实使化目录和配置文件 启动服务 登陆mysql 其它操作   参考文档: 一.新建一个启动服务的目录 mkdir /usr/local/docker/mysql cd /usr/local/docker/mysql 二…

    MySQL 2023年4月13日
    00
合作推广
合作推广
分享本页
返回顶部