MySQL进阶之路索引失效的11种情况详析

这篇文章主要介绍了MySQL查询优化中的11种常见情况,包括索引的使用和优化策略,通过这些策略,开发者可以显著提升查询性能,需要的朋友可以参考下

目录
  • 前言
  • 图示
  • 1. 使用不等式操作符(!=, <, >)
  • 2. 使用 OR 连接多个条件
  • 3. 对索引字段进行计算操作
  • 4. 对索引字段进行类型转换
  • 5. LIKE 头部模糊查询
  • 6. NULL 值的查询
  • 7. DISTINCT 或 GROUP BY 操作
  • 8. JOIN 查询中没有适当的索引
  • 9. 排序(ORDER BY)与索引不匹配
  • 10. 表连接顺序不当
  • 11. 启用 NO_INDEX 或 FORCE INDEX 提示时的索引失效
  • 总结

前言

在MySQL的查询优化中,索引是一项至关重要的技术,它能够大大提升数据检索的效率。本文将讨论这11种常见情况,帮助开发者更好地理解索引的使用及优化。

图示

1. 使用不等式操作符(!=, <, >)

  • 例子
    SELECT * FROM users WHERE age != 30; 
    
  • 原理:索引通常用于等值查询(=)或范围查询(><),不等式操作无法有效利用索引。
  • 解决方案:避免使用不等式条件,改用范围查询。
    SELECT * FROM users WHERE age NOT BETWEEN 30 AND 30;
    SELECT * FROM users WHERE`age > 30`AND`age < 30;
    

2. 使用 OR 连接多个条件

  • 例子
    SELECT * FROM users WHERE age = 30 OR gender = 'male'; 
    
  • 原理OR 会导致多个独立查询,尤其当每个条件涉及不同列时,索引不会完全失效,会快速定位有索引列部分,无索引列进行全部扫描。
  • 解决方案:使用 UNION 替代 OR、创建联合索引。
    --创建联合索引
    create index idx_users_age_gender on users(age,gender);
    SELECT * FROM users WHERE age = 30 OR gender = 'male'; 
    --使用UNION合并子查询
    SELECT * FROM users WHERE age = 30
    UNION
    SELECT * FROM users WHERE gender = 'male';
    

3. 对索引字段进行计算操作

  • 例子
    SELECT * FROM orders WHERE YEAR(order_date) = 2024; 
    
  • 原理:计算和函数操作会改变数据的表现形式,索引无法直接应用。这个查询中,使用了 YEAR(order_date) 函数来提取 order_date 字段的年份,与 2024 进行比较。
  • 解决方案:1.改为直接存储处理后的数据。2.直接改为当前字段的范围查询。
    --范围查询
    SELECT * FROM orders WHERE order_date >= '2024-01-01' AND order_date < '2025-01-01';
    --直接存储处理后的数据
    ALTER TABLE orders add column order_year INT; -- 新增字段 order_year
    UPDATE orders SET order_year = YEAR(order_date); 
    SELECT * FROM orders WHERE order_year = 2024;
    

4. 对索引字段进行类型转换

  • 例子
    SELECT * FROM users WHERE CAST(age AS CHAR) = '30'; 
    
  • 原理:类型转换会导致数据类型与索引数据类型不匹配,索引失效。
  • 解决方案:确保查询条件的数据类型与索引数据类型一致,避免使用类型转换。

5. LIKE 头部模糊查询

  • 例子
    SELECT * FROM users WHERE name LIKE '%john';   
    
  • 原理LIKE 查询以 % 开头时,索引无法使用,因为数据库无法提前确定匹配的范围。
  • 解决方案:避免在 LIKE 查询中使用前缀 %,改为 LIKE 'john%'
    SELECT * FROM users WHERE name LIKE 'john%';   
    

6. NULL 值的查询

  • 例子
    SELECT * FROM users WHERE age IS NULL; 
    
  • 原理:索引对 NULL 值的查询支持有限,可能无法高效利用。
  • 解决方案:避免频繁查询 NULL 值,或者为包含 NULL 值的字段设计专门的索引、将 NULL值替换为其他默认值。
    -- 使用IFNULL() 函数
    SELECT * FROM users WHERE IFNULL(age, -1) = -1;
    -- 使用COALESCE() 函数
    SELECT * FROM users WHERE COALESCE(age, -1) = -1;
    --使用 NOT NULL 约束,修改字段默认值为 0
    ALTER TABLE users MODIFY age NOT NULL DEFAULT 0;
    

7. DISTINCT 或 GROUP BY 操作

  • 例子
    SELECT DISTINCT age FROM users;
    SELECT age, COUNT(*) FROM users GROUP BY age;
    
  • 原理DISTINCT 和 GROUP BY 操作需要去重或聚合数据。这些操作不能直接利用索引来返回唯一结果,通常会导致数据库扫描整个表(即全表扫描),尤其是在没有合适索引的情况下。
  • 解决方案:使用合适的索引(例如 GROUP BY 列上创建索引),或者将查询分解成多个步骤。
    --创建索引
    CREATE INDEX idx_users_age ON users(age);
    SELECT age, COUNT(*) FROM users GROUP BY age;
    
    --子查询获取去重结果集再查询
    SELECT age, COUNT(*) 
    FROM users 
    WHERE age IN (
        SELECT DISTINCT age 
        FROM users 
        WHERE age IS NOT NULL
    )
    GROUP BY age;
    

8. JOIN 查询中没有适当的索引

  • 例子
    SELECT * FROM users u JOIN orders o ON u.id = o.user_id; 
    
  • 原理:如果连接条件没有索引,JOIN 查询可能会导致全表扫描。
  • 解决方案:为连接字段创建索引,确保连接操作高效执行。
    CREATE INDEX idx_user_id ON orders(user_id);
    CREATE INDEX idx_user_id_users ON users(id);
    
  • 使用合适的连接类型:在某些情况下,使用 INNER JOINLEFT JOIN 或其他连接类型可以影响查询性能,选择最合适的连接方式可以帮助优化性能。

9. 排序(ORDER BY)与索引不匹配

  • 例子
    SELECT * FROM users ORDER BY name DESC,age ASC; 
    
  • 原理:如果索引的顺序与查询的排序要求不匹配,可能无法利用索引。
  • 解决方案:确保查询的排序方式与索引的顺序一致,使用复合索引支持多种排序需求。
    -- 创建复合索引
    CREATE INDEX idx_name_age ON users(name DESC, age ASC); 
    SELECT * FROM users ORDER BY name DESC, age ASC;
    

10. 表连接顺序不当

  • 例子
    SELECT * FROM users u JOIN orders o ON u.id = o.user_id WHERE o.order_date > '2024-01-01'; 
    
  • 原理:连接顺序不当可能导致某些表的索引无法使用,从而降低查询性能。
  • 解决方案:根据数据量和索引设计优化 JOIN 顺序。
    -- 使用子查询(筛选大表后再去连接)
    SELECT * FROM 
    (SELECT * FROM orders WHERE order_date > '2024-01-01') o
    JOIN users u ON u.id = o.user_id;
    -- 小表驱动大表(如果users表有100条,orders有20万数据)
    -- 使用 STRAIGHT_JOIN 强制左表为驱动表
    SELECT * 
    FROM users u
    STRAIGHT_JOIN orders o ON u.id = o.user_id
    WHERE o.order_date > '2024-01-01';
    

11. 启用 NO_INDEX 或 FORCE INDEX 提示时的索引失效

  • 例子
    SELECT * FROM users FORCE INDEX (idx_name) WHERE age = 30;
    
  • 原理:强制索引或禁止索引可能导致查询优化器无法选择最优的执行计划。
  • 解决方案:避免使用 FORCE INDEX 或 NO_INDEX,让数据库自动选择最优索引。

总结

在 SQL 查询优化中,合适的索引设计和查询结构调整是提高性能的关键。通过以下措施可以避免常见的性能瓶颈:

  • 使用适当的索引来加速 DISTINCTGROUP BYJOIN 和 ORDER BY 操作。
  • 优化连接顺序,确保合理使用索引。
  • 避免强制使用或禁用索引,允许查询优化器自动选择最优执行计划。

到此这篇关于MySQL进阶之路索引失效的11种情况的文章就介绍到这了,更多相关MySQL索引失效情况内容请搜索骃骐网以前的文章或继续浏览下面的相关文章希望大家以后多多支持骃骐网!

您可能感兴趣的文章:

  • Mysql索引会失效的几种情况分析
  • mysql索引失效的五种情况分析
  • MySQL中索引失效的常见场景与规避方法
  • MySQL索引失效的几种情况汇总
  • MySQL索引失效的几种情况详析
  • 解决mysql模糊查询索引失效问题的几种方法
  • MySQL索引失效原理
  • mysql索引失效的常见九种原因图文详解
  • MySQL导致索引失效的几种情况
  • MySQL索引失效的几种情况图文详解

相关推荐:

Python 消费 RabbitMQ 消息时遇到数据库连接失效(InterfaceError)的最佳重连处理

数据库连接失效时,RabbitMQ消费者不应直接basic_nack(requeue=True)触发无限重试,而应先重建DB连接、本地带退避重试(如tenacity指数退避3次),失败后basic_nack(requeue=False)入死信队列,并确保队列已正确绑定DLX。 数据库连接失效时,RabbitMQ 消费者不能直接重试消息 遇到 InterfaceError(比如 MySQL 的 “L...

Python类中列表洗牌失效:如何正确实现独立随机化

在Python类初始化时直接对传入列表调用random.shuffle()会导致所有实例共享同一份被修改的数据,根本原因是未创建副本而进行了原地修改。解决方法是使用.copy()或list()构造新列表后再洗牌。 在python类初始化时直接对传入列表调用`random.shuffle()`会导致所有实例共享同一份被修改的数据,根本原因是未创建副本而进行了原地修改。解决方法是使用`.copy()`...

Python类中列表洗牌失效:如何正确实现独立实例的随机化

当在类初始化时对传入列表调用random.shuffle()却得到相同结果,根本原因是多个实例共享同一列表对象;需通过深拷贝(如.copy())创建独立副本后再洗牌,并避免使用内置类型名(如list)作参数名。 当在类初始化时对传入列表调用random.shuffle()却得到相同结果,根本原因是多个实例共享同一列表对象;需通过深拷贝(如.copy())创建独立副本后再洗牌,并避免使用内置类型名(...

Keras Embedding层中input_length参数失效的解决方案

在Keras 3.x(包括TensorFlow内置Keras)中,Embedding层已移除input_length参数,需改用input_shape显式指定输入序列长度,否则会报错“Unrecognized keyword arguments”。 在keras 3.x(包括tensorflow内置keras)中,`embedding`层已移除`input_length`参数,需改用`input_...

如何修复Python中条件循环内列表随机化失效的问题

本文揭示了在while循环中反复调用随机化函数却始终无法满足约束条件的根本原因:原始timetable被重复追加列而非重置,导致约束检查始终作用于旧数据,新生成的列被忽略。 本文揭示了在while循环中反复调用随机化函数却始终无法满足约束条件的根本原因:原始timetable被重复追加列而非重置,导致约束检查始终作用于旧数据,新生成的列被忽略。 在优化类问题(如医院手术排程)中,使用随机初始化+约...

解决jQuery动态加载内容事件失效问题:事件委托与重新绑定机制详解

本教程深入探讨了jQuery中动态加载HTML内容后,原有的事件绑定失效的问题。通过对比unbind().click()和$(document).on()两种处理方式,详细介绍了事件委托(Event Delegation)作为首选解决方案的原理和实现。同时,也探讨了在特定场景下重新绑定事件的策略,并提供了清晰的代码示例和最佳实践,旨在帮助开发者有效管理动态内容的交互行为。问题解析:动态内容事件失效...

CSS样式怎么失效_CSS样式不生效常见原因与排查解决教程

答案:CSS样式不生效通常由文件未加载、选择器错误、优先级冲突、语法错误或缓存问题导致。首先检查link路径是否正确,确认CSS文件在Network面板成功加载;接着用开发者工具检查元素的Computed样式,查看是否有样式被覆盖或划掉;排查选择器是否匹配,避免拼写错误;分析CSS优先级,确认是否存在更高权重的规则覆盖当前样式;检查语法如分号、括号是否缺失,属性名是否拼错;清除浏览器缓存或强制刷新...

解决HTML align="center" 属性失效问题:专业指南

本文旨在解决HTML中align="center"属性失效的问题,并提供替代方案。通过分析inline元素特性,解释了该属性失效的原因。文章详细介绍了如何使用CSS样式text-align: center以及结合div元素来实现文本居中对齐,并提供了相应的代码示例和注意事项,帮助开发者更好地掌握HTML文本居中的实现方法。 在HTML开发中,我们经常需要将文本内容居中显示。早期,align="ce...

解决 NextAuth 中 getToken 在服务器端失效的问题

解决 NextAuth 中 getToken 在服务器端失效的问题 如上文摘要所述,getToken 函数在 NextAuth.js 应用中用于获取用户的身份验证 token。然而,在服务器端环境,例如 getServerSideProps 或中间件中,直接调用 getToken 可能会返回 null。这通常是因为服务器端发起的请求(例如使用 fetch)默认情况下不会自动携带客户端的 cooki...