1. 索引基础概念与重要性
说明: 索引是数据库表中用于快速定位数据的数据结构。
-- 创建一张简单表,没有索引
CREATE TABLE users (
id INT NOT NULL,
username VARCHAR(50),
email VARCHAR(100),
PRIMARY KEY (id)
);
-- 查询无索引情况下全表扫描示例
EXPLAIN SELECT * FROM users WHERE username = 'alice';
运行EXPLAIN会显示type为ALL,说明全表扫描,性能差。
2. MySQL存储引擎对索引支持差异
-- 查看表的存储引擎
SHOW TABLE STATUS WHERE Name = 'users';
-- 创建MyISAM和InnoDB表示例
CREATE TABLE myisam_table (
id INT PRIMARY KEY,
data VARCHAR(100)
) ENGINE=MyISAM;
CREATE TABLE innodb_table (
id INT PRIMARY KEY,
data VARCHAR(100)
) ENGINE=InnoDB;
InnoDB支持事务和聚簇索引,MyISAM不支持事务且索引结构不同。
3. MySQL索引数据结构及工作原理
-- 查看当前索引
SHOW INDEX FROM users;
-- 创建一个B+树索引(普通索引)
CREATE INDEX idx_username ON users(username);
-- 查看索引后,使用EXPLAIN
EXPLAIN SELECT * FROM users WHERE username = 'alice';
B+树结构索引加速等值查询和范围查询。
4. 详细索引类型解析
-- 主键索引(创建表时)
CREATE TABLE products (
product_id INT PRIMARY KEY,
name VARCHAR(100)
);
-- 唯一索引
CREATE UNIQUE INDEX idx_email ON users(email);
-- 普通索引
CREATE INDEX idx_name ON users(username);
-- 全文索引(MyISAM或InnoDB 5.6+)
CREATE FULLTEXT INDEX idx_content ON articles(content);
全文索引用于全文搜索。
5. 主键索引与聚簇索引深度解析
-- InnoDB主键索引自动聚簇,查看原理示意(无SQL)
-- 通过辅助索引查询演示
CREATE TABLE orders (
order_id INT PRIMARY KEY,
user_id INT,
order_date DATE,
INDEX idx_user_id (user_id)
);
-- 查询时通过辅助索引回表
EXPLAIN SELECT * FROM orders WHERE user_id = 123;
辅助索引叶子节点存储主键,回表查询整行。
6. 复合索引设计与最左前缀原则
-- 创建复合索引
CREATE INDEX idx_user_date ON orders(user_id, order_date);
-- 查询使用索引
EXPLAIN SELECT * FROM orders WHERE user_id = 123 AND order_date = '2025-06-21';
-- 只使用最左前缀
EXPLAIN SELECT * FROM orders WHERE user_id = 123;
-- 不能单独使用user_id后面的字段索引
EXPLAIN SELECT * FROM orders WHERE order_date = '2025-06-21';
查询只能利用从最左边开始连续的索引列。
7. 索引失效全面分析与解决方案
-- 使用函数导致索引失效
EXPLAIN SELECT * FROM users WHERE LOWER(username) = 'alice';
-- 优化方案,避免函数
EXPLAIN SELECT * FROM users WHERE username = 'alice';
-- 前置通配符失效
EXPLAIN SELECT * FROM users WHERE username LIKE '%lice';
-- 优化使用全文索引
CREATE FULLTEXT INDEX idx_username_ft ON users(username);
SELECT * FROM users WHERE MATCH(username) AGAINST('lice' IN BOOLEAN MODE);
函数和前置通配符会导致索引失效。
8. 覆盖索引与回表机制详解
-- 覆盖索引示例
CREATE INDEX idx_username_email ON users(username, email);
-- 查询只用索引字段,无需回表
EXPLAIN SELECT username, email FROM users WHERE username = 'alice';
-- 查询需要回表
EXPLAIN SELECT email FROM users WHERE username = 'alice';
覆盖索引避免访问数据行,提升效率。
9. 索引与事务、锁机制的关系
-- 开启事务
START TRANSACTION;
-- 通过索引更新数据,减少锁范围
UPDATE orders SET order_date = '2025-06-22' WHERE order_id = 1001;
-- 未使用索引,可能导致表锁或范围锁
UPDATE orders SET order_date = '2025-06-22' WHERE user_id = 123;
COMMIT;
索引有助于减少锁冲突,提升并发。
10. EXPLAIN详解及执行计划优化
-- 查看执行计划
EXPLAIN SELECT * FROM orders WHERE user_id = 123;
-- 使用ANALYZE EXPLAIN(MySQL 8.0+)
ANALYZE EXPLAIN SELECT * FROM orders WHERE user_id = 123;
分析type、rows、possible_keys等列来判断索引使用效率。
11. 索引的维护与监控工具
-- 查看索引信息
SHOW INDEX FROM orders;
-- 统计表和索引信息
ANALYZE TABLE orders;
-- 优化表和索引
OPTIMIZE TABLE orders;
-- 查看索引IO等待情况
SELECT * FROM performance_schema.table_io_waits_summary_by_index_usage WHERE OBJECT_NAME='orders';
定期维护索引保证查询效率。
12. 索引优化实战案例解析
-- 情况:订单按用户和日期筛选慢
-- 解决:创建复合索引
CREATE INDEX idx_user_date ON orders(user_id, order_date);
-- 验证效果
EXPLAIN SELECT * FROM orders WHERE user_id = 123 AND order_date BETWEEN '2025-01-01' AND '2025-06-30';
实战中合理设计索引,显著提升查询性能。
13. 附录:索引相关SQL语法大全
-- 创建索引
CREATE INDEX idx_col ON table(col);
-- 创建唯一索引
CREATE UNIQUE INDEX idx_unique_col ON table(col);
-- 删除索引
DROP INDEX idx_col ON table;
-- 查看索引
SHOW INDEX FROM table;
-- 查看执行计划
EXPLAIN SELECT * FROM table WHERE col='value';
如需具体业务场景代码示例、脚本自动化或针对某类查询的索引设计方案,告诉我!
发表回复