
1. MySQL索引基础概念解析索引是MySQL数据库中用于加速数据检索的关键机制它就像图书馆的目录系统——没有索引时查找数据需要全表扫描相当于逐本检查每本书而合理设计的索引能让查询效率提升几个数量级。在MySQL中索引本质上是一种特殊的数据结构它存储了表中某些列的值及其对应记录的物理位置。索引的工作原理可以类比字典的拼音检索当我们知道某个字的读音时可以直接翻到对应拼音的页码而不需要从第一页开始逐个查找。MySQL常用的B树索引结构同样遵循这个原理通过多级索引快速定位数据位置。注意虽然索引能显著提升查询速度但每个额外的索引都会增加写操作INSERT/UPDATE/DELETE的开销因为数据库需要同步维护索引结构。这就是为什么不能简单地为所有字段都创建索引。2. MySQL索引类型详解2.1 主键索引PRIMARY KEY主键索引是MySQL中最严格的索引类型它具有以下特性唯一性不允许重复值非空不允许NULL值聚集索引InnoDB引擎数据行实际存储在索引的叶子节点中创建示例CREATE TABLE users ( id INT NOT NULL AUTO_INCREMENT, username VARCHAR(50) NOT NULL, PRIMARY KEY (id) -- 定义主键索引 );2.2 唯一索引UNIQUE唯一索引保证列值的唯一性但允许NULL值常用于避免数据重复ALTER TABLE users ADD UNIQUE (username);2.3 普通索引INDEX最基本的索引类型没有唯一性约束CREATE INDEX idx_email ON users(email);2.4 复合索引多列索引在多个列上建立的联合索引遵循最左前缀原则CREATE INDEX idx_name_age ON employees(last_name, first_name, age);2.5 全文索引FULLTEXT专为文本搜索设计的特殊索引类型支持MATCH AGAINST语法ALTER TABLE articles ADD FULLTEXT(title, body);3. 索引底层结构与原理3.1 B树索引结构MySQL最常用的索引结构是B树它具有以下特点多路平衡查找树保持查询效率稳定所有数据都存储在叶子节点非叶子节点只存键值叶子节点通过指针连接支持范围查询![B树索引结构示意图] 此处应为B树结构图示描述各层节点关系3.2 哈希索引Memory引擎支持的索引类型适用于等值查询通过哈希函数计算键值位置查询时间复杂度O(1)不支持范围查询和排序3.3 聚集索引 vs 非聚集索引聚集索引InnoDB主键数据行与索引存储在一起非聚集索引二级索引索引与数据行分离存储4. 索引创建与管理实践4.1 创建索引的最佳实践-- 创建表时定义索引 CREATE TABLE products ( id INT PRIMARY KEY, name VARCHAR(100), category_id INT, price DECIMAL(10,2), INDEX idx_category (category_id), INDEX idx_price (price) ); -- 修改表添加索引 ALTER TABLE orders ADD INDEX idx_customer_date (customer_id, order_date); -- 创建覆盖索引 CREATE INDEX idx_covering ON employees(department_id, salary) INCLUDE (name);4.2 查看索引信息SHOW INDEX FROM table_name; EXPLAIN SELECT * FROM table_name WHERE condition;4.3 索引维护操作-- 重建索引InnoDB ALTER TABLE table_name ENGINEInnoDB; -- 优化表整理碎片 OPTIMIZE TABLE table_name; -- 删除索引 DROP INDEX index_name ON table_name;5. 索引优化与性能调优5.1 索引选择原则高选择性原则选择区分度高的列如ID、用户名最左前缀原则复合索引的列顺序很重要覆盖索引原则尽量让索引包含查询所需全部字段短索引原则对长字符串考虑前缀索引5.2 常见索引失效场景使用函数或表达式SELECT * FROM users WHERE YEAR(create_time) 2023; -- 索引失效隐式类型转换SELECT * FROM users WHERE phone 13800138000; -- phone是varchar类型使用OR条件除非所有列都有索引SELECT * FROM users WHERE name John OR age 30;使用不等于(!或)SELECT * FROM users WHERE status ! 1;5.3 执行计划分析使用EXPLAIN解读关键字段type从最好到最差依次为 system const eq_ref ref range index ALLpossible_keys可能使用的索引key实际使用的索引rows预估需要检查的行数Extra额外信息Using index/Using filesort等6. 高级索引策略6.1 索引下推ICPMySQL 5.6特性将WHERE条件过滤下推到存储引擎层SET optimizer_switch index_condition_pushdownon;6.2 自适应哈希索引InnoDB自动为频繁访问的索引页构建哈希索引加速查询。6.3 索引合并优化当查询条件涉及多个索引时MySQL可能合并索引扫描结果SELECT * FROM users WHERE name John OR email johnexample.com;7. 索引设计实战案例7.1 电商平台索引设计-- 商品表 CREATE TABLE products ( id BIGINT PRIMARY KEY, name VARCHAR(200) NOT NULL, category_id INT NOT NULL, price DECIMAL(10,2) NOT NULL, stock INT NOT NULL DEFAULT 0, status TINYINT NOT NULL DEFAULT 1, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, INDEX idx_category_status (category_id, status), INDEX idx_price (price), INDEX idx_created (created_at) ); -- 订单表 CREATE TABLE orders ( id BIGINT PRIMARY KEY, user_id BIGINT NOT NULL, status TINYINT NOT NULL, total_amount DECIMAL(12,2) NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, INDEX idx_user_status (user_id, status), INDEX idx_created (created_at) );7.2 社交平台索引设计-- 用户关系表 CREATE TABLE user_relations ( user_id BIGINT NOT NULL, friend_id BIGINT NOT NULL, relation_type TINYINT NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (user_id, friend_id), INDEX idx_friend (friend_id) ); -- 动态信息表 CREATE TABLE posts ( id BIGINT PRIMARY KEY, user_id BIGINT NOT NULL, content TEXT NOT NULL, visibility TINYINT NOT NULL DEFAULT 1, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, INDEX idx_user_visibility (user_id, visibility), FULLTEXT INDEX idx_content (content) );8. 索引监控与维护8.1 索引使用情况监控-- 查看索引使用统计 SELECT * FROM sys.schema_index_statistics WHERE table_schema your_database; -- 查看未使用的索引 SELECT * FROM sys.schema_unused_indexes;8.2 定期索引维护策略每周分析表更新统计信息ANALYZE TABLE important_table;每月优化碎片化严重的表OPTIMIZE TABLE heavily_updated_table;季度审查并删除无用索引8.3 索引大小监控SELECT table_name, index_name, ROUND(stat_value * innodb_page_size / 1024 / 1024, 2) AS size_mb FROM mysql.innodb_index_stats WHERE database_name your_db AND stat_name size;9. 特殊场景索引优化9.1 分页查询优化低效写法SELECT * FROM large_table ORDER BY id LIMIT 1000000, 10;优化方案SELECT * FROM large_table WHERE id (SELECT id FROM large_table ORDER BY id LIMIT 1000000, 1) ORDER BY id LIMIT 10;9.2 JSON字段索引MySQL 8.0支持JSON字段索引CREATE TABLE products ( id INT PRIMARY KEY, attributes JSON, INDEX idx_attributes_price ((CAST(attributes-$.price AS DECIMAL(10,2)))) );9.3 地理空间索引CREATE TABLE locations ( id INT PRIMARY KEY, name VARCHAR(100), position POINT NOT NULL SRID 4326, SPATIAL INDEX(position) );10. 索引相关工具与技巧10.1 pt-index-usage工具Percona Toolkit中的工具用于分析慢查询日志中的索引使用情况pt-index-usage slow.log -u root -p password --host localhost10.2 使用sys库分析索引MySQL 8.0的sys库提供多种索引分析视图-- 查看冗余索引 SELECT * FROM sys.schema_redundant_indexes; -- 查看索引统计信息 SELECT * FROM sys.schema_index_statistics;10.3 在线DDL操作MySQL 5.6支持在线索引变更ALTER TABLE large_table ADD INDEX idx_new_column(new_column), ALGORITHMINPLACE, LOCKNONE;在实际工作中我发现很多性能问题都源于不当的索引设计。一个常见的误区是在低选择性的列上创建索引比如在性别字段上建索引通常不会带来性能提升。另一个经验是复合索引的列顺序应该按照选择性从高到低排列并且要考虑查询中最常使用的列组合。定期使用EXPLAIN分析查询执行计划是优化索引策略的有效方法。