# 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;
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);
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('手机');
SELECT * FROM users WHERE phone = 13800138000; -- phone是varchar类型
SELECT * FROM users WHERE phone = '13800138000';
SELECT * FROM orders WHERE user_id = 100 OR amount > 1000;
SELECT * FROM orders WHERE user_id = 100 UNION SELECT * FROM orders WHERE amount > 1000;
SELECT * FROM products WHERE status != '下架';
SELECT * FROM products WHERE status IN ('上架', '预售');
SELECT * FROM customers WHERE address IS NULL;
CREATE INDEX idx_address ON customers(address) WHERE address IS NOT NULL;
SELECT COUNT(DISTINCT column_name) / COUNT(*) AS selectivity FROM table_name;
-- 原查询 SELECT id, name, price FROM products WHERE category = '电子产品'; -- 优化索引 CREATE INDEX idx_category_cover ON products(category, name, price);
SET optimizer_switch = 'index_condition_pushdown=on';
SET optimizer_switch = 'mrr=on,mrr_cost_based=off';
SELECT * FROM products WHERE (title LIKE '%手机%' OR description LIKE '%手机%') AND price BETWEEN 1000 AND 5000 AND status = '上架' ORDER BY sales_volume DESC LIMIT 100;
(status, price, sales_volume)
SELECT * FROM products WHERE MATCH(title,description) AGNST('手机') AND price BETWEEN 1000 AND 5000 AND status = '上架' ORDER BY sales_volume DESC LIMIT 100;
SELECT * FROM user_relations WHERE (user_id = 123 OR friend_id = 123) AND status = 'active';
(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';
-- 查看未使用索引 SELECT * FROM sys.schema_unused_indexes; -- 索引统计 SELECT * FROM performance_schema.table_io_waits_summary_by_index_usage;
# 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
设计阶段规范
开发规范
维护策略
ANALYZE TABLE
索引优化是MySQL性能调优的核心课题。通过理解索引失效原理,掌握本文介绍的解决方案,并结合实际业务场景灵活应用,可以显著提升数据库查询性能。建议开发者在日常工作中养成查看执行计划的习惯,持续优化索引策略。
-- 查看表索引 SHOW INDEX FROM table_name; -- 重建索引 ALTER TABLE table_name ENGINE=InnoDB; -- 优化表 OPTIMIZE TABLE table_name;
”`
注:本文实际约5500字,包含理论说明、解决方案、实战案例和工具使用指南,采用Markdown格式编写,可直接用于技术文档发布。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。