本文档详细介绍TiDB复合索引与覆盖索引的使用方法,包括索引概念、设计、实施方案、实战案例等内容。风哥教程参考TiDB官方文档索引相关内容,适合DBA和开发人员在日常使用TiDB时参考。更多视频教程www.fgedu.net.cn
Part01-基础概念与理论知识
1.1 复合索引概念
复合索引是基于多个列创建的索引,也称为多列索引。
- 定义:基于两个或多个列创建的索引
- 特点:遵循最左前缀原则
- 适用场景:多列查询条件
- 加速多列查询
- 减少索引数量
- 提高查询性能
- 支持最左前缀匹配
1.2 覆盖索引概念
覆盖索引是指索引包含查询所需的所有列,无需回表获取数据。
- 定义:索引包含查询所需的所有列
- 特点:避免回表操作,提高查询性能
- 适用场景:频繁的列查询
- 避免回表操作,提高查询性能
- 减少IO操作
- 降低内存使用
- 适用于频繁的列查询
1.3 索引类型差异
| 特性 | 复合索引 | 覆盖索引 | 普通索引 |
|——|———-|———-|———-|
| 索引列数 | 多个 | 多个(包含查询列) | 单个 |
| 最左前缀原则 | 适用 | 适用 | 不适用 |
| 回表操作 | 可能需要 | 不需要 | 需要 |
| 查询性能 | 较快 | 最快 | 一般 |
| 存储开销 | 较大 | 较大 | 较小 |
| 适用场景 | 多列查询 | 频繁的列查询 | 单 column query |
Part02-生产环境规划与建议
2.1 复合索引设计
2.1.1 复合索引列顺序
## 1. 选择原则
– 将最常用的列放在前面
– 将选择性高的列放在前面
– 将范围查询的列放在后面
– 遵循最左前缀原则
## 2. 最左前缀原则
– 复合索引 (a, b, c) 可以用于:
– WHERE a = ?
– WHERE a = ? AND b = ?
– WHERE a = ? AND b = ? AND c = ?
– 但不能用于:
– WHERE b = ?
– WHERE c = ?
– WHERE b = ? AND c = ?
## 3. 示例
– 对于查询:WHERE status = ? AND created_at > ?
– 复合索引:(status, created_at)
– 对于查询:WHERE user_id = ? AND status = ?
– 复合索引:(user_id, status)
2.1.2 复合索引数量控制
## 1. 影响因素
– 写入性能:索引越多,写入开销越大
– 存储开销:索引占用存储空间
– 管理复杂度:索引越多,管理越复杂
## 2. 推荐数量
– 每个表的复合索引数量不宜过多(建议不超过3个)
– 避免创建冗余的复合索引
– 定期清理无用的复合索引
## 3. 冗余索引识别
– 识别前缀冗余:如 (a, b) 和 (a)
– 识别顺序冗余:如 (a, b) 和 (b, a)
– 识别功能冗余:如 (a, b) 和 (a, b, c)
2.2 覆盖索引设计
2.2.1 覆盖索引列选择
## 1. 选择原则
– 包含查询所需的所有列
– 包含WHERE条件中的列
– 包含ORDER BY和GROUP BY中的列
– 控制索引大小
## 2. 示例
– 对于查询:SELECT name, age FROM fgedu_users WHERE status = ?
– 覆盖索引:(status, name, age)
– 对于查询:SELECT user_id, amount FROM fgedu_orders WHERE status = ? AND created_at > ?
– 覆盖索引:(status, created_at, user_id, amount)
## 3. 注意事项
– 覆盖索引列不宜过多,避免索引过大
– 对于频繁查询的列组合,考虑创建覆盖索引
– 定期评估覆盖索引的有效性
2.2.2 覆盖索引性能考虑
## 1. 查询性能
– 避免回表操作,提高查询速度
– 减少IO操作,降低系统负载
– 提高内存利用率
## 2. 写入性能
– 增加写入开销(需要更新索引)
– 索引越大,写入开销越大
## 3. 存储开销
– 覆盖索引占用更多存储空间
– 索引列越多,存储空间越大
## 4. 权衡考虑
– 平衡查询性能和写入性能
– 平衡存储开销和查询性能
– 根据业务需求调整覆盖索引策略
学习交流加群风哥QQ113257174
2.3 使用场景分析
## 复合索引使用场景
– 多列查询:WHERE a = ? AND b = ?
– 范围查询:WHERE a = ? AND b > ?
– 排序查询:ORDER BY a, b
– 分组查询:GROUP BY a, b
## 覆盖索引使用场景
– 频繁的列查询:SELECT a, b FROM table WHERE c = ?
– 统计查询:SELECT COUNT(*) FROM table WHERE a = ?
– 排序查询:SELECT a, b FROM table WHERE c = ? ORDER BY a
– 连接查询:SELECT a, b FROM table1 JOIN table2 ON table1.id = table2.id WHERE table1.c = ?
## 组合使用场景
– 复合覆盖索引:同时满足复合索引和覆盖索引的条件
– 多列查询且需要覆盖:SELECT a, b FROM table WHERE c = ? AND d = ?
– 复杂查询优化:通过覆盖索引减少回表操作
Part03-生产环境项目实施方案
3.1 复合索引实施方案
3.1.1 创建复合索引
## 1. 创建表时创建复合索引
CREATE TABLE fgedu_orders (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT,
order_no VARCHAR(32) UNIQUE,
amount DECIMAL(10,2) NOT NULL,
status VARCHAR(20),
created_at DATETIME,
INDEX idx_user_id_status (user_id, status),
INDEX idx_status_created_at (status, created_at)
);
## 2. 为现有表添加复合索引
ALTER TABLE fgedu_orders ADD INDEX idx_user_id_created_at (user_id, created_at);
## 3. 查看复合索引
SHOW INDEX FROM fgedu_orders;
## 4. 删除复合索引
ALTER TABLE fgedu_orders DROP INDEX idx_user_id_status;
3.1.2 复合索引优化
## 1. 分析查询模式
– 收集常用查询语句
– 分析WHERE条件
– 分析ORDER BY和GROUP BY子句
## 2. 优化复合索引列顺序
– 将最常用的列放在前面
– 将选择性高的列放在前面
– 将范围查询的列放在后面
## 3. 测试复合索引效果
– 使用EXPLAIN分析执行计划
– 测试查询性能
– 调整复合索引列顺序
## 4. 示例
– 对于查询:WHERE user_id = ? AND status = ?
– 复合索引:(user_id, status)
– 对于查询:WHERE status = ? AND created_at > ?
– 复合索引:(status, created_at)
3.2 覆盖索引实施方案
3.2.1 创建覆盖索引
## 1. 识别覆盖索引机会
– 分析频繁查询的列组合
– 确定查询所需的所有列
– 设计包含这些列的索引
## 2. 创建覆盖索引
– 对于查询:SELECT name, age FROM fgedu_users WHERE status = ?
– 覆盖索引:(status, name, age)
– 对于查询:SELECT user_id, amount FROM fgedu_orders WHERE status = ? AND created_at > ?
– 覆盖索引:(status, created_at, user_id, amount)
## 3. 查看覆盖索引
SHOW INDEX FROM fgedu_users;
## 4. 删除覆盖索引
ALTER TABLE fgedu_users DROP INDEX idx_status_name_age;
3.2.2 覆盖索引验证
## 1. 使用EXPLAIN验证
– 查看执行计划中的”Extra”字段
– 覆盖索引会显示”Using index”
## 2. 示例
mysql> EXPLAIN SELECT name, age FROM fgedu_users WHERE status = ‘active’;
## 3. 性能测试
– 比较使用覆盖索引和不使用覆盖索引的查询性能
– 测量查询响应时间
– 分析IO操作次数
## 4. 覆盖索引维护
– 定期重建覆盖索引
– 更新统计信息
– 监控覆盖索引使用情况
3.3 索引维护与管理
3.3.1 复合索引维护
## 1. 重建复合索引
– 当数据分布发生变化时
– 当索引碎片严重时
– 当查询性能下降时
## 2. 更新统计信息
– 定期更新统计信息
– 确保优化器生成正确的执行计划
## 3. 监控复合索引
– 监控复合索引的使用情况
– 分析复合索引的性能
– 调整复合索引策略
## 4. 复合索引维护脚本
“`bash
#!/bin/bash
# composite_index_maintenance.sh
# from:www.itpux.com.qq113257174.wx:itpux-com
# web: `http://www.fgedu.net.cn`
# 更新统计信息
mysql -u root -p -e “ANALYZE TABLE fgedu_orders;”
# 检查复合索引使用情况
mysql -u root -p -e “SHOW INDEX FROM fgedu_orders;”
“`
3.3.2 覆盖索引维护
## 1. 重建覆盖索引
– 当数据分布发生变化时
– 当索引碎片严重时
– 当查询性能下降时
## 2. 更新统计信息
– 定期更新统计信息
– 确保优化器生成正确的执行计划
## 3. 监控覆盖索引
– 监控覆盖索引的使用情况
– 分析覆盖索引的性能
– 调整覆盖索引策略
## 4. 覆盖索引维护脚本
“`bash
#!/bin/bash
# covering_index_maintenance.sh
# from:www.itpux.com.qq113257174.wx:itpux-com
# web: `http://www.fgedu.net.cn`
# 更新统计信息
mysql -u root -p -e “ANALYZE TABLE fgedu_users;”
# 检查覆盖索引使用情况
mysql -u root -p -e “SHOW INDEX FROM fgedu_users;”
“`
Part04-生产案例与实战讲解
4.1 复合索引实战案例
## 1. 案例背景
– 表:fgedu_orders(订单表)
– 数据量:1000万行
– 常用查询:
– WHERE user_id = ? AND status = ?
– WHERE status = ? AND created_at > ?
## 2. 分析过程
– 检查当前索引:只有主键索引
– 分析查询执行计划:全表扫描
– 设计复合索引策略
## 3. 实施步骤
### 步骤1:创建复合索引
mysql> ALTER TABLE fgedu_orders ADD INDEX idx_user_id_status (user_id, status);
mysql> ALTER TABLE fgedu_orders ADD INDEX idx_status_created_at (status, created_at);
### 步骤2:测试查询性能
mysql> EXPLAIN SELECT * FROM fgedu_orders WHERE user_id = 1 AND status = ‘completed’;
mysql> SELECT * FROM fgedu_orders WHERE user_id = 1 AND status = ‘completed’;
mysql> EXPLAIN SELECT * FROM fgedu_orders WHERE status = ‘completed’ AND created_at > ‘2024-01-01’;
mysql> SELECT * FROM fgedu_orders WHERE status = ‘completed’ AND created_at > ‘2024-01-01’;
### 步骤3:性能对比
– 无索引:1.5秒
– 复合索引:0.05秒
## 4. 优化效果
– 查询性能提升30倍
– 减少数据扫描范围
– 提高系统响应速度
4.2 覆盖索引实战案例
## 1. 案例背景
– 表:fgedu_users(用户表)
– 数据量:500万行
– 常用查询:SELECT name, age FROM fgedu_users WHERE status = ?
## 2. 分析过程
– 检查当前索引:只有主键索引和status单列索引
– 分析执行计划:使用status索引,但需要回表
– 设计覆盖索引策略
## 3. 实施步骤
### 步骤1:创建覆盖索引
mysql> ALTER TABLE fgedu_users ADD INDEX idx_status_name_age (status, name, age);
### 步骤2:测试查询性能
mysql> EXPLAIN SELECT name, age FROM fgedu_users WHERE status = ‘active’;
mysql> SELECT name, age FROM fgedu_users WHERE status = ‘active’;
### 步骤3:性能对比
– 普通索引:0.15秒
– 覆盖索引:0.05秒
## 4. 优化效果
– 查询性能提升3倍
– 避免回表操作
– 减少IO操作
4.3 性能分析与优化
## 1. 测试环境
– 数据库:TiDB 7.5.0
– 服务器:8核16GB
– 表:fgedu_orders(1000万行)
## 2. 测试场景
– 无索引
– 单列索引
– 复合索引
– 覆盖索引
## 3. 查询性能测试
### 场景1:多列查询
– 无索引:1.5秒
– 单列索引:0.5秒
– 复合索引:0.05秒
– 覆盖索引:0.04秒
### 场景2:范围查询
– 无索引:1.8秒
– 单列索引:0.8秒
– 复合索引:0.1秒
– 覆盖索引:0.08秒
### 场景3:排序查询
– 无索引:2.0秒
– 单列索引:1.0秒
– 复合索引:0.2秒
– 覆盖索引:0.15秒
## 4. 写入性能测试
– 无索引:1000行/秒
– 单列索引:800行/秒
– 复合索引:700行/秒
– 覆盖索引:650行/秒
## 5. 存储开销测试
– 单列索引:50MB
– 复合索引:100MB
– 覆盖索引:150MB
## 6. 优化建议
– 对于多列查询,使用复合索引
– 对于频繁的列查询,使用覆盖索引
– 平衡查询性能和写入性能
– 合理设置复合索引的列顺序
Part05-风哥经验总结与分享
5.1 最佳实践
TiDB复合索引与覆盖索引的最佳实践:
- 复合索引最佳实践:
- 根据查询模式设计复合索引
- 合理设置复合索引的列顺序
- 遵循最左前缀原则
- 控制复合索引数量
- 覆盖索引最佳实践:
- 识别频繁查询的列组合
- 创建包含查询所需所有列的索引
- 控制覆盖索引的大小
- 定期评估覆盖索引的有效性
- 通用最佳实践:
- 根据业务需求和查询模式选择合适的索引类型
- 定期维护索引,保持良好性能
- 监控索引使用情况,及时调整索引策略
- 平衡查询性能和写入性能
5.2 性能优化技巧
## 1. 复合索引优化技巧
– 选择合适的列顺序:最常用、选择性高的列放在前面
– 利用最左前缀原则:设计复合索引时考虑所有可能的查询组合
– 避免冗余索引:删除功能重复的索引
– 定期分析查询模式:根据实际查询调整复合索引
## 2. 覆盖索引优化技巧
– 识别频繁查询的列组合:创建针对性的覆盖索引
– 控制索引大小:只包含必要的列
– 利用覆盖索引加速排序:将排序列包含在索引中
– 监控覆盖索引使用情况:确保索引被有效使用
## 3. 查询优化技巧
– 确保查询条件包含复合索引的前缀列
– 避免在索引列上使用函数
– 合理使用EXPLAIN分析执行计划
– 优化SQL语句,确保使用索引
## 4. 写入优化技巧
– 控制索引数量:避免过多的索引
– 批量写入数据:减少索引更新次数
– 合理设置事务大小:避免大事务
– 利用并行写入提高写入性能
## 5. 维护优化技巧
– 定期重建索引:保持索引性能
– 更新统计信息:确保优化器生成正确的执行计划
– 监控索引使用情况:及时调整索引策略
– 清理无用索引:减少存储开销和写入开销
5.3 常见问题与解决
## 1. 复合索引问题
### 问题1:复合索引列顺序不当
– 症状:查询未使用复合索引
– 原因:列顺序不符合查询模式
– 解决:调整复合索引列顺序,将最常用的列放在前面
### 问题2:最左前缀原则未遵循
– 症状:查询未使用复合索引
– 原因:查询条件未包含复合索引的前缀列
– 解决:优化查询语句,确保包含前缀列,或调整索引顺序
### 问题3:复合索引过多
– 症状:写入性能下降,存储空间占用大
– 原因:创建了过多的复合索引
– 解决:清理无用的复合索引,合并重复的索引
## 2. 覆盖索引问题
### 问题1:覆盖索引过大
– 症状:存储开销大,写入性能下降
– 原因:覆盖索引包含过多列
– 解决:只包含必要的列,控制索引大小
### 问题2:覆盖索引未被使用
– 症状:查询仍需回表
– 原因:查询条件或选择列与覆盖索引不匹配
– 解决:调整覆盖索引列,确保包含查询所需的所有列
### 问题3:覆盖索引维护成本高
– 症状:索引重建时间长
– 原因:覆盖索引过大
– 解决:合理设计覆盖索引,避免包含过多列
## 3. 通用问题
### 问题1:索引未被使用
– 症状:查询执行计划显示全表扫描
– 原因:查询条件未包含索引列,或在索引列上使用了函数
– 解决:优化查询语句,确保查询条件包含索引列,避免在索引列上使用函数
### 问题2:索引碎片
– 症状:查询性能下降
– 原因:索引碎片严重
– 解决:重建索引
### 问题3:统计信息过期
– 症状:执行计划异常
– 原因:统计信息未及时更新
– 解决:定期更新统计信息
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
