本文档风哥主要介绍TiDB索引设计与优化相关知识,包括索引基础、TiDB索引特性、索引类型、索引设计原则、索引策略、索引维护、索引创建、索引优化、索引评估等内容,风哥教程参考TiDB官方文档索引章节,适合DBA人员在学习和测试中使用,如果要应用于生产环境则需要自行确认。
Part01-基础概念与理论知识
1.1 索引基础
索引的核心概念:
- 索引:一种数据结构,用于加速数据查询。
- B+树:TiDB使用的索引数据结构,适合范围查询。
- 索引键:索引的列或列组合。
- 索引值:索引键对应的值。
- 回表:通过索引找到数据后,需要回到表中获取完整数据的过程。
- 加速数据查询
- 加速排序和分组操作
- 保证数据唯一性
- 减少数据扫描范围
1.2 TiDB索引特性
TiDB的索引特性:
## 分布式索引
– 索引与数据一样,分布式存储在TiKV中
– 自动分片,无需手动管理
– 支持水平扩展
## 聚簇索引
– 主键索引是聚簇索引
– 数据与索引存储在一起
– 提高查询性能
## 非聚簇索引
– 二级索引是非聚簇索引
– 存储索引键和主键值
– 需要回表查询完整数据
## 覆盖索引
– 索引包含查询所需的所有列
– 避免回表,提高查询性能
## 索引统计信息风哥提示:
– 自动收集和更新统计信息
– 优化器使用统计信息生成执行计划
– 支持手动更新统计信息
1.3 索引类型
TiDB支持的索引类型:
- 主键索引:唯一标识表中的每一行数据,默认自动创建。
- 唯一索引:确保索引列的值唯一,允许NULL值。
- 普通索引:加速数据查询,不保证唯一性。
- 前缀索引:对字符串列的前缀部分创建索引,减少索引大小。
- 全文索引:用于全文搜索,支持中文分词。
- 空间索引:用于地理空间数据查询。
- 表达式索引:对表达式的结果创建索引。
Part02-生产环境规划与建议
2.1 索引设计原则
索引设计的基本原则:
## 1. 选择性原则
– 选择选择性高的列作为索引列
– 选择性 = 不同值的数量 / 总行数
– 选择性越高,索引效果越好
## 2. 最左前缀原则
– 联合索引的查询条件必须从索引的最左列开始
– 否则索引不会被使用
## 3. 覆盖索引原则
– 索引包含查询所需的所有列
– 避免回表,提高查询性能
## 4. 适度原则
– 避免过度索引
– 每个索引都会增加写操作的开销
– 一般每个表的索引数量不超过5个
## 5. 按需原则
– 根据实际查询需求创建索引
– 分析慢查询日志,识别需要索引的列
– 定期清理无用的索引
2.2 索引策略
索引策略:
## 1. 单列索引
– 适用于单个列的查询
– 简单,易于维护
– 适合选择性高的列
## 2. 联合索引
– 适用于多列查询
– 遵循最左前缀原则
– 可以减少索引数量
## 3. 前缀索引
– 适用于长字符串列
– 减少索引大小
– 提高查询性能
## 4. 唯一索引
– 确保数据唯一性
– 提高查询性能
– 适合作为主键或唯一标识符
## 5. 全文索引
– 适用于全文搜索
– 支持中文分词
– 提高搜索性能
## 6. 空间索引
– 适用于地理空间数据
– 支持空间查询
– 提高空间查询性能
2.3 索引维护
索引维护:
- 定期分析表:更新统计信息,确保优化器生成准确的执行计划。
- 重建索引:修复索引碎片,提高索引性能。
- 删除无用索引:减少索引维护开销,提高写性能。
- 监控索引使用情况:识别未使用的索引,及时清理。
- 索引备份:确保索引数据安全。
学习交流加群风哥QQ113257174
Part03-生产环境项目实施方案
3.1 索引创建
3.1.1 创建单列索引
## 1. 创建普通索引
$ mysql -h 192.168.1.100 -P 4000 -u fgedu -p -e “CREATE INDEX idx_age ON fgedudb.fgedu_users(age);”
## 2. 创建唯一索引
$ mysql -h 192.168.1.100 -P 4000 -u fgedu -p -e “CREATE UNIQUE INDEX idx_email ON fgedudb.fgedu_users(email);”
## 3. 创建前缀索引
$ mysql -h 192.168.1.100 -P 4000 -u fgedu -p -e “CREATE INDEX idx_name ON fgedudb.fgedu_users(name(10));”
## 4. 创建全文索引
$ mysql -h 192.168.1.100 -P 4000 -u fgedu -p -e “CREATE FULLTEXT INDEX idx_content ON fgedudb.fgedu_articles(content);”
## 5. 创建空间索引
$ mysql -h 192.168.1.100 -P 4000 -u fgedu -p -e “CREATE SPATIAL INDEX idx_location ON fgedudb.fgedu_places(location);”
3.1.2 创建联合索引
## 1. 创建两列联合索引
$ mysql -h 192.168.1.100 -P 4000 -u fgedu -p -e “CREATE INDEX idx_age_gender ON fgedudb.fgedu_users(age, gender);”
## 2. 创建三列联合索引
$ mysql -h 192.168.1.100 -P 4000 -u fgedu -p -e “CREATE INDEX idx_category_price_sales ON fgedudb.fgedu_products(category_id, price, sales);”
## 3. 创建唯一联合索引
$ mysql -h 192.168.1.100 -P 4000 -u fgedu -p -e “CREATE UNIQUE INDEX idx_user_product ON fgedudb.fgedu_orders(user_id, product_id);”
3.2 索引优化
3.2.1 索引使用分析
## 1. 查看索引使用情况
$ mysql -h 192.168.1.100 -P 4000 -u fgedu -p -e “SHOW INDEX FROM fgedudb.fgedu_users;”
## 2. 查看慢查询日志
$ tail -f /tidb/app/tidb-deploy/tidb-4000/log/tidb-slow.log
## 3. 分析执行计划
$ mysql -h 192.168.1.100 -P 4000 -u fgedu -p -e “EXPLAIN SELECT * FROM fgedudb.fgedu_users WHERE age > 30 AND gender = ‘male’;”
## 4. 使用Performance Schema
$ mysql -h 192.168.1.100 -P 4000 -u fgedu -p -e “SELECT * FROM performance_schema.table_io_waits_summary_by_index_usage WHERE object_schema = ‘fgedudb’ AND object_name = ‘fgedu_users’;”
3.2.2 索引优化策略
## 1. 优化索引列顺序
– 将选择性高的列放在联合索引的前面
– 按照查询频率调整索引列顺序
– 遵循最左前缀原则
## 2. 优化索引类型
– 根据查询类型选择合适的索引类型
– 对于范围查询,使用普通索引
– 对于唯一性要求,使用唯一索引
## 3. 优化索引覆盖
– 创建覆盖索引,避免回表
– 只查询需要的列
– 减少数据传输
## 4. 优化索引大小
– 使用前缀索引减少索引大小
– 避免在大字段上创建索引
– 定期清理无用索引
## 5. 优化索引维护
– 定期分析表,更新统计信息
– 重建索引,修复索引碎片
– 监控索引使用情况,及时调整
3.3 索引评估
3.3.1 索引性能评估
## 1. 使用Sysbench测试
$ sysbench –db-driver=mysql –mysql-host=192.168.1.100 –mysql-port=4000 –mysql-user=fgedu –mysql-password=password –mysql-db=fgedudb –table-size=1000000 –tables=10 –threads=16 –time=300 oltp_read_write run
## 2. 测试特定查询
$ time mysql -h 192.168.1.100 -P 4000 -u fgedu -p -e “SELECT * FROM fgedudb.fgedu_users WHERE age > 30 AND gender = ‘male’ ORDER BY age DESC LIMIT 100;”
## 3. 分析执行计划
$ mysql -h 192.168.1.100 -P 4000 -u fgedu -p -e “EXPLAIN ANALYZE SELECT * FROM fgedudb.fgedu_users WHERE age > 30 AND gender = ‘male’ ORDER BY age DESC LIMIT 100;”
## 4. 监控索引使用
$ mysql -h 192.168.1.100 -P 4000 -u fgedu -p -e “SELECT * FROM information_schema.statistics WHERE table_schema = ‘fgedudb’ AND table_name = ‘fgedu_users’;”
Part04-生产案例与实战讲解
4.1 电商行业索引优化案例
某电商平台索引优化案例:
– 业务场景:电商平台商品搜索
– 问题:商品搜索响应时间长,影响用户体验
– 数据量:商品表数据量达到1000万
– QPS:高峰期达到5000QPS
# 问题分析
1. 慢查询分析:发现商品搜索SQL执行时间超过1秒
2. 执行计划分析:全表扫描,没有使用索引
3. 查询模式:
– 根据分类ID和价格范围查询
– 按销量排序
– 分页显示
# 优化措施
1. 创建联合索引:
CREATE INDEX idx_category_price_sales ON fgedudb.fgedu_products(category_id, price, sales);
2. 优化SQL:
SELECT id, name, price, sales FROM fgedudb.fgedu_products WHERE category_id = 1 AND price > 100 ORDER BY sales DESC LIMIT 20;
3. 执行计划分析:
+————————-+———+———–+—————————————–+———————————————-+
| id | estRows | task | access object | operator info |
+————————-+———+———–+—————————————–+———————————————-+
| TopN_7 | 20.00 | root | | offset:0, count:20, sort:fgedu_products.sales DESC |
| └─IndexRangeScan_6 | 10000.00 | cop[tikv] | table:fgedu_products, index:idx_category_price_sales | range:[1,100,+inf], keep order:false |
+————————-+———+———–+—————————————–+———————————————-+
# 优化效果
– 查询响应时间:从1秒降低到100ms以内
– 系统QPS:从5000提升到10000
– 用户体验:明显改善,商品搜索速度大幅提升
4.2 金融行业索引优化案例
某银行索引优化案例:
– 业务场景:银行交易查询
– 问题:交易历史查询响应时间长,影响业务处理效率
– 数据量:交易表数据量达到5000万
– QPS:高峰期达到2000QPS
# 问题分析
1. 慢查询分析:发现交易历史查询SQL执行时间超过2秒
2. 执行计划分析:使用了全表扫描和临时表
3. 查询模式:
– 根据用户ID和交易日期查询
– 按交易日期排序
– 分页显示
# 优化措施
1. 创建联合索引:
CREATE INDEX idx_user_date ON fgedudb.fgedu_transactions(user_id, transaction_date);
2. 优化SQL:
SELECT transaction_id, transaction_date, amount, type FROM fgedudb.fgedu_transactions WHERE user_id = 12345 AND transaction_date BETWEEN ‘2024-01-01’ AND ‘2024-01-31’ ORDER BY transaction_date DESC;
3. 分区表:
ALTER TABLE fgedudb.fgedu_transactions PARTITION BY RANGE(YEAR(transaction_date)) (
PARTITION p2023 VALUES LESS THAN (2024),
PARTITION p2024 VALUES LESS THAN (2025),
PARTITION p2025 VALUES LESS THAN (2026)
);
# 优化效果
– 查询响应时间:从2秒降低到200ms以内
– 系统QPS:从2000提升到5000
– 业务处理效率:显著提高,客户满意度提升
4.3 制造业索引优化案例
某制造企业索引优化案例:
– 业务场景:生产数据统计
– 问题:生产报表生成时间长,影响决策效率
– 数据量:生产表数据量达到2000万
– 执行频率:每天执行一次
# 问题分析
1. 慢查询分析:发现生产报表SQL执行时间超过5分钟
2. 执行计划分析:使用了多个表的复杂JOIN操作
3. 查询模式:
– 关联产品表和订单表
– 按产品名称分组
– 按总金额排序
# 优化措施
1. 创建索引:
CREATE INDEX idx_order_product_date ON fgedudb.fgedu_orders(product_id, order_date);
CREATE INDEX idx_product_name ON fgedudb.fgedu_products(product_name);
2. 优化SQL:
SELECT p.product_name, SUM(o.quantity) as total_quantity, SUM(o.amount) as total_amount FROM fgedudb.fgedu_orders o JOIN fgedudb.fgedu_products p ON o.product_id = p.product_id WHERE o.order_date BETWEEN ‘2024-01-01’ AND ‘2024-01-31’ GROUP BY p.product_id, p.product_name ORDER BY total_amount DESC;
3. 物化视图:
CREATE MATERIALIZED VIEW fgedu_order_summary AS SELECT product_id, SUM(quantity) as total_quantity, SUM(amount) as total_amount, DATE(order_date) as order_date FROM fgedudb.fgedu_orders GROUP BY product_id, DATE(order_date);
# 优化效果
– 查询响应时间:从5分钟降低到30秒以内
– 报表生成效率:显著提高,决策速度加快
– 系统负载:明显降低
Part05-风哥经验总结与分享
5.1 索引设计最佳实践
索引设计的最佳实践:
- 分析查询模式:了解业务的查询模式,根据查询需求设计索引。
- 选择合适的索引类型:根据查询类型选择合适的索引类型。
- 遵循最左前缀原则:联合索引的查询条件必须从最左列开始。
- 创建覆盖索引:索引包含查询所需的所有列,避免回表。
- 控制索引数量:每个表的索引数量不超过5个,避免过度索引。
- 定期分析表:更新统计信息,确保优化器生成准确的执行计划。
- 监控索引使用情况:识别未使用的索引,及时清理。
5.2 常见错误与避免方法
## 1. 过度索引
– 错误:创建过多的索引,增加写操作的开销
– 避免方法:只创建必要的索引,定期清理无用的索引
## 2. 索引列顺序错误
– 错误:联合索引的列顺序不合理,导致索引无法被使用
– 避免方法:将选择性高的列放在前面,按照查询频率调整顺序
## 3. 索引列类型不匹配
– 错误:查询条件的数据类型与索引列类型不匹配,导致索引失效
– 避免方法:确保查询条件的数据类型与索引列类型一致
## 4. 在索引列上使用函数
– 错误:在索引列上使用函数,导致索引失效
– 避免方法:避免在索引列上使用函数,或者使用表达式索引
## 5. 忽略统计信息
– 错误:不更新统计信息,导致优化器生成错误的执行计划
– 避免方法:定期分析表,更新统计信息
## 6. 不考虑数据分布
– 错误:索引设计没有考虑数据分布情况,导致索引效果不佳
– 避免方法:根据数据分布情况调整索引策略
## 7. 忽略查询性能测试
– 错误:创建索引后没有进行性能测试,无法验证索引效果
– 避免方法:创建索引后进行性能测试,验证索引效果
5.3 持续优化建议
持续优化建议:
- 建立索引审核机制:对新创建的索引进行审核,确保符合最佳实践。
- 定期分析慢查询:定期分析慢查询日志,识别需要优化的查询。
- 优化索引:根据查询模式调整索引,避免过度索引。
- 更新统计信息:定期更新统计信息,确保优化器生成准确的执行计划。
- 监控索引使用情况:实时监控索引使用情况,及时发现和处理问题。
- 培训开发人员:对开发人员进行索引设计培训,提高索引设计质量。
- 使用工具:使用索引优化工具,辅助识别和解决索引问题。
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
