Mysql索引失效的解决方法

发布时间:2021-11-02 11:34:39 作者:小新
来源:亿速云 阅读:264
# MySQL索引失效的解决方法

## 引言

在数据库性能优化中,索引是提升查询效率最有效的手段之一。然而在实际应用中,我们经常会遇到索引失效的情况,导致查询性能急剧下降。本文将深入剖析MySQL索引失效的常见场景,并提供系统化的解决方案,帮助开发者避免性能陷阱。

## 一、索引基础回顾

### 1.1 索引的工作原理

MySQL索引采用B+树数据结构,通过减少磁盘I/O次数来加速数据检索。当执行查询时,优化器会评估是否使用索引以及使用哪个索引。

### 1.2 常见索引类型
- **主键索引**:唯一且非空的聚簇索引
- **普通索引**:基本的非聚簇索引
- **唯一索引**:保证列值唯一性
- **复合索引**:多列组合的索引
- **全文索引**:用于文本搜索

## 二、索引失效的典型场景

### 2.1 违反最左前缀原则

#### 问题表现
对于复合索引`(a,b,c)`,以下查询会导致索引失效:
```sql
SELECT * FROM table WHERE b = 1 AND c = 2;

解决方案

2.2 对索引列进行运算或函数操作

问题表现

SELECT * FROM users WHERE YEAR(create_time) = 2023;

解决方案

SELECT * FROM users 
WHERE create_time BETWEEN '2023-01-01' AND '2023-12-31';
ALTER TABLE users ADD COLUMN create_year INT AS (YEAR(create_time));
CREATE INDEX idx_create_year ON users(create_year);

2.3 使用LIKE通配符前置

问题表现

SELECT * FROM products WHERE name LIKE '%手机%';

解决方案

SELECT * FROM products WHERE name LIKE '苹果%';
CREATE FULLTEXT INDEX ft_idx_name ON products(name);
SELECT * FROM products WHERE MATCH(name) AGNST('手机');

2.4 类型转换导致失效

问题表现

SELECT * FROM users WHERE phone = 13800138000;  -- phone是varchar类型

解决方案

SELECT * FROM users WHERE phone = '13800138000';

2.5 OR条件使用不当

问题表现

SELECT * FROM orders WHERE user_id = 100 OR amount > 1000;

解决方案

SELECT * FROM orders WHERE user_id = 100
UNION
SELECT * FROM orders WHERE amount > 1000;

2.6 使用NOT、!=、<>操作符

问题表现

SELECT * FROM products WHERE status != '下架';

解决方案

SELECT * FROM products WHERE status IN ('上架', '预售');

2.7 索引列参与IS NULL判断

问题表现

SELECT * FROM customers WHERE address IS NULL;

解决方案

CREATE INDEX idx_address ON customers(address) WHERE address IS NOT NULL;

三、高级优化策略

3.1 索引选择性优化

计算方法

SELECT 
  COUNT(DISTINCT column_name) / COUNT(*) AS selectivity
FROM table_name;

优化建议

3.2 使用覆盖索引

实现方式

-- 原查询
SELECT id, name, price FROM products WHERE category = '电子产品';

-- 优化索引
CREATE INDEX idx_category_cover ON products(category, name, price);

3.3 索引下推优化(ICP)

启用条件

配置方法

SET optimizer_switch = 'index_condition_pushdown=on';

3.4 MRR优化

多范围读取优化

SET optimizer_switch = 'mrr=on,mrr_cost_based=off';

四、实战案例分析

4.1 电商平台商品搜索优化

原始查询

SELECT * FROM products 
WHERE (title LIKE '%手机%' OR description LIKE '%手机%')
AND price BETWEEN 1000 AND 5000
AND status = '上架'
ORDER BY sales_volume DESC
LIMIT 100;

优化方案

  1. 建立全文索引
  2. 创建复合索引(status, price, sales_volume)
  3. 重写查询:
SELECT * FROM products 
WHERE MATCH(title,description) AGNST('手机')
AND price BETWEEN 1000 AND 5000
AND status = '上架'
ORDER BY sales_volume DESC
LIMIT 100;

4.2 社交网络好友关系查询

原始查询

SELECT * FROM user_relations 
WHERE (user_id = 123 OR friend_id = 123)
AND status = 'active';

优化方案

  1. 使用UNION优化OR条件
  2. 创建两个索引(user_id, status)(friend_id, status)
SELECT * FROM user_relations WHERE user_id = 123 AND status = 'active'
UNION
SELECT * FROM user_relations WHERE friend_id = 123 AND status = 'active';

五、监控与诊断工具

5.1 EXPLN详解

关键指标解读

5.2 性能模式监控

常用表

-- 查看未使用索引
SELECT * FROM sys.schema_unused_indexes;

-- 索引统计
SELECT * FROM performance_schema.table_io_waits_summary_by_index_usage;

5.3 Slow Query Log分析

配置方法

# my.cnf配置
slow_query_log = 1
slow_query_log_file = /var/log/mysql/mysql-slow.log
long_query_time = 1
log_queries_not_using_indexes = 1

六、预防索引失效的最佳实践

  1. 设计阶段规范

    • 遵循最小化原则选择索引列
    • 为常用查询模式设计复合索引
    • 避免过度索引(单表索引不超过5-6个)
  2. 开发规范

    • 统一使用预编译语句
    • 避免SELECT * 查询
    • 事务保持短小精悍
  3. 维护策略

    • 定期执行ANALYZE TABLE
    • 监控索引使用情况
    • 及时清理冗余索引

结语

索引优化是MySQL性能调优的核心课题。通过理解索引失效原理,掌握本文介绍的解决方案,并结合实际业务场景灵活应用,可以显著提升数据库查询性能。建议开发者在日常工作中养成查看执行计划的习惯,持续优化索引策略。

附录

A. 常用索引维护命令

-- 查看表索引
SHOW INDEX FROM table_name;

-- 重建索引
ALTER TABLE table_name ENGINE=InnoDB;

-- 优化表
OPTIMIZE TABLE table_name;

B. 推荐阅读

”`

注:本文实际约5500字,包含理论说明、解决方案、实战案例和工具使用指南,采用Markdown格式编写,可直接用于技术文档发布。

推荐阅读:
  1. MySQL索引失效的原因有哪些
  2. mysql索引为什么会失效

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

mysql

上一篇:小程序中如何对网络请求进行二次封装

下一篇:怎么分析和提高C/C++程序的编译速度

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》