MySQL 中使用索引一定有效吗?如何排查索引效果?

虽然索引是提升 MySQL 查询性能的常见手段,但并不是所有情况下索引都会有效。索引的使用取决于查询条件、数据分布、索引设计等多个因素。如果索引未能有效使用,可能导致查询性能不如预期。


1. 索引未必一定有效的情况

以下是一些常见的导致 MySQL 不使用索引的情况:

(1)索引选择性差

  • 如果索引列的数据选择性较低(例如:某个列的值大部分相同),索引可能不会被使用。此时,MySQL 会选择全表扫描,而不是使用索引,因为全表扫描的成本可能比索引扫描更低。

  • 示例

    SELECT * FROM users WHERE gender = 'Male';

    如果 gender 列只有 'Male''Female' 两个值,索引选择性差,MySQL 可能选择全表扫描。

(2)范围查询

  • 使用了范围查询(如 BETWEEN><LIKE 等)时,索引会被部分使用,通常只能利用范围查询前的字段索引。

  • 示例

    SELECT * FROM users WHERE age > 30 AND name = 'Alice';

    在这种查询中,age > 30 是范围查询,MySQL 可能只使用 age 索引,忽略 name 索引。

(3)对索引列使用了函数或表达式

  • 在查询中对索引列使用了函数(如 YEAR(date_column))或进行表达式计算时,索引可能会失效,因为计算后值与存储的索引值不匹配。

  • 示例

    SELECT * FROM orders WHERE YEAR(order_date) = 2023;

    YEAR(order_date) 会导致索引失效,除非使用适当的索引,如索引覆盖完整的 order_date 列。

(4)隐式类型转换

  • 在查询中,如果传入的查询条件数据类型与索引列的数据类型不同,MySQL 可能会进行隐式类型转换,导致索引失效。

  • 示例

    SELECT * FROM users WHERE age = '25';

    如果 age 列是 INT 类型,而查询条件是字符串 '25',会导致类型不匹配,进而导致索引失效。

(5)使用 OR 连接条件

  • 在查询中使用 OR 时,如果 OR 连接的条件不能充分利用索引,MySQL 可能会选择全表扫描。

  • 示例

    SELECT * FROM users WHERE name = 'Alice' OR age = 30;

    如果 nameage 列分别有索引,MySQL 可能不能有效使用这两个索引,而是选择全表扫描。


2. 如何排查索引效果

要确保索引的有效使用,并排查可能的索引问题,可以使用以下方法:

(1)使用 EXPLAIN 命令分析查询计划

  • EXPLAIN 命令可以显示 MySQL 执行查询时选择的执行计划,帮助我们判断是否使用了索引。

  • 示例

    EXPLAIN SELECT * FROM users WHERE name = 'Alice' AND age = 30;

    EXPLAIN 的输出会显示是否使用了索引、使用了哪个索引、索引扫描的类型等信息。

    常见的 EXPLAIN 输出解释

    • key:显示使用的索引。
    • type:连接类型,ALL 表示全表扫描,range 表示范围扫描,ref 表示索引查找。
    • rows:MySQL 预计扫描的行数。

(2)使用 SHOW WARNINGS 排查索引失效原因

  • 如果查询没有使用索引,MySQL 会通过 SHOW WARNINGS 显示相关警告信息,指示索引未能使用的原因。

  • 示例

    SHOW WARNINGS;

(3)查看慢查询日志

  • 通过启用慢查询日志,可以查看哪些查询可能因为没有使用索引而执行缓慢。

  • 配置慢查询日志

    slow_query_log = 1
    slow_query_log_file = /path/to/slow-query.log
    long_query_time = 1

    慢查询日志记录了执行时间超过指定阈值的查询,帮助我们定位可能的索引问题。


3. 优化索引使用的建议

(1)优化查询条件

  • 确保查询条件字段与索引顺序匹配,尤其是在多列联合索引的情况下,遵循最左前缀原则。

(2)避免函数和类型转换

  • 尽量避免在查询条件中使用对索引列的函数或表达式。保持查询条件与索引列的数据类型一致。

(3)减少不必要的 OR 操作

  • 使用 IN 替代 OR,或者根据需要重写查询以避免导致索引失效的 OR 条件。

(4)增加覆盖索引

  • 对查询中常用的字段,设计覆盖索引,这样 MySQL 可以直接从索引中返回结果,避免回表操作。

4. 总结

索引的使用并非在所有情况下都有效。要确保索引能够提升查询性能,除了合理设计索引,还需要排查影响索引使用的因素,如范围查询、隐式类型转换、函数应用等。通过使用 EXPLAIN 分析查询执行计划,结合慢查询日志和 SHOW WARNINGS,可以帮助排查和优化索引效果。

MySQL 中使用索引一定有效吗?如何排查索引效果?的更多相关文章

  1. MYSQL中常用的强制性操作(例如强制索引)

    mysql常用的hint 对于经常使用oracle的朋友可能知道,oracle的hint功能种类很多,对于优化sql语句提供了很多方法.同样,在mysql里,也有类似的hint功能.下面介绍一些常用的 ...

  2. mysql中一半会选择什么样的字段为索引?(含索引创建删除查看公式)

    一.数据量庞大的数据做索引 二.该字段经常出现在where的后面,以条件形式存在,经常被用户搜索的字段 三.很少被增删改的字段,因为增删改后,索引会重新排序 索引的创建 create index 索引 ...

  3. Mysql中给有记录的表添加唯一索引

    ALTER IGNORE TABLE neeqs ADD UNIQUE KEY `unique` (`seccode`, `enddate`, `f002v`);

  4. mysql中limit 和 limit 与 offset 的用法(效果相同,用法不通过)

    例1,假设数据库表student存在13条数据. 代码示例: 语句1:select * from student limit 9,4 语句2:slect * from student limit 4 ...

  5. Mysql中索引的 创建,查看,删除,修改

    创建索引 MySQL创建索引的语法如下: ? 1 2 3 CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name [USING index_type] ON ...

  6. MySQL中的空间扩展

    目录 19.1. 前言 19.2. OpenGIS几何模型 19.2.1. Geometry类的层次 19.2.2. 类Geometry 19.2.3. 类Point 19.2.4. 类Curve 1 ...

  7. mysql InnoDB index 主键采用聚簇索引,二级索引不采用聚簇索引

    原文链接 我的归纳: (1)InnoDB的主键采用聚簇索引存储,使用的是B+Tree作为索引结构,但是叶子节点存储的是索引值和数据本身(注意和MyISAM的不同). (2)InnoDB的二级索引不使用 ...

  8. MySQL中地理位置数据扩展geometry的使用心得

    最近学习了些MySQL geometry数据存储和计算,在这里记录下. 1. 环境 geometry推荐在5.6版本以上使用,尽管大部分功能在5.5已经可用,除了距离计算函数st_distance等新 ...

  9. mysql中的key primary key 和unique key

    mysql 中key就等同于index 所以 key:普通索引 unique key:唯一索引,就是这一列不能重复 primary key:主键索引,就是不能为空,且主键索引不是完全相同时,插入新数据 ...

  10. 探究MySQL中SQL查询的成本

    成本 什么是成本,即SQL进行查询的花费的时间成本,包含IO成本和CPU成本. IO成本:即将数据页从硬盘中读取到内存中的读取时间成本.通常1页就是1.0的成本. CPU成本:即是读取和检测是否满足条 ...

随机推荐

  1. 056_带标签的break和continue 057_方法的定义_形参_实参_返回值_语句块 058_方法的重载overload 059_递归算法详解_递归和迭代效率测试

    056_带标签的break和continue(替代被取消的goto语句) 加个计数器: /** * 带标签的Break和Continue * * @author * */public class Te ...

  2. oracle 根据排序去重取第一条

    原文转自 https://www.jianshu.com/p/d5c0a355890b,感谢作者styone分享. SELECT t.* FROM (SELECT a.*, row_number ( ...

  3. 解决“yarn : 无法加载文件 C:\Users\quber\AppData\Roaming\npm\yarn.ps1,因为在此系统上禁止运行脚本”问题

    1.问题描述 我们在使用yarn命令的时候,可能会出现如下图所示的错误: 2.解决办法 出现此错误的原因是本地计算机上运行你编写的未签名脚本和来自其他用户的签名脚本,可以使用如下命令将计算机上的执行策 ...

  4. Schreier–Sims 算法

    好看的实现. #include<bits/stdc++.h> using namespace std; #define int long long const int maxn=105; ...

  5. 表治理-Iceberg元数据合并-metadata.json文件

    一.背景描述 元数据文件随时间增多,导致查询变慢.通过如下方式可以指定metadata个数,超过指定数量自动清理. metadata文件对应Iceberg概念是Snapshots 二.解决方案 1.在 ...

  6. vue集成amis

    一.下载amis 方式一:git下载sdk.tar.gz,https://github.com/baidu/amis/releases 方式二:npm i amis 来下载,在 node_module ...

  7. JUC并发—1.Java集合包底层源码剖析

    大纲 1.为什么要对JDK源码剖析 2.ArrayList源码一:基本原理以及优缺点 3.ArrayList源码二:核心方法的原理 4.ArrayList源码三:数组扩容以及元素拷贝 5.Linked ...

  8. JUC并发—2.Thread源码分析及案例应用

    大纲 1.什么是线程以及并发编程 2.微服务注册中心案例 3.以工作线程模式开启微服务的注册和心跳线程 4.微服务注册中心的服务注册功能 5.微服务注册中心的心跳续约功能 6.微服务的存活状态监控线程 ...

  9. 《Indie Tools • 半月刊》第001期

    引言:独立开发者工具分享 <INDIE TOOLS>专注于分享独立开发出海精选.最新.最实用的工具. 欢迎订阅半月刊:<INDIE TOOLS • 半月刊> 如果本文能给你提供 ...

  10. [BZOJ3771] Triple 题解

    <关于贫穷的樵夫拥有 40000 把斧头这件事>. 相当于是多项式乘法,但是得带容斥,具体自己看代码吧. #include<bits/stdc++.h> using names ...