1. 慢查询优化的常见误区

1.1 "有索引就能用"的误解

很多开发者认为只要创建索引就能提升查询速度,实际上索引未被正确使用的情况普遍存在。例如:

-- 场景:用户表user_info含组合索引(city, gender)
SELECT * FROM user_info 
WHERE gender = 'male'   -- 索引字段gender在联合索引的第二位
ORDER BY create_time DESC LIMIT 100;

此时数据库会进行全表扫描,因为查询条件不符合最左前缀原则。优化方案需要调整索引顺序或修改查询条件。

1.2 过度索引的代价

某电商平台订单表添加了14个索引后,发现写入性能下降70%。测试环境验证:

-- 原始表结构
CREATE TABLE orders (
    id INT PRIMARY KEY,
    user_id INT,
    product_id INT,
    status TINYINT,
    create_time DATETIME,
    INDEX idx_user (user_id),
    INDEX idx_product (product_id),
    INDEX idx_status (status),
    -- 此处省略其他8个索引...
);

-- 插入性能对比(10万次插入)
未添加索引:38秒
添加索引后:1分52秒

每个索引都会增加写操作成本,需要平衡查询效率与写入性能。

1.3 盲目使用强制索引

开发者通过FORCE INDEX强制指定索引可能引发更严重问题:

-- 错误示例:强制使用过期的索引
SELECT * FROM orders FORCE INDEX (create_time_index)
WHERE status = 2 AND amount > 100;

当数据分布发生变化时(如status=2的数据占比从5%增长到60%),原本高效的索引可能变成性能杀手。


2. 索引选择的黄金法则

2.1 索引选择的三要素

  • 基数选择性:字段不同值的数量与总行数的比值
  • 查询频率:该字段出现在WHERE条件的频率
  • 数据分布:字段值的分布是否均匀
-- 示例:分析字段选择性
SELECT 
    COUNT(DISTINCT status)/COUNT(*) AS status_selectivity,
    COUNT(DISTINCT user_id)/COUNT(*) AS user_selectivity 
FROM orders;

-- 返回结果:
status_selectivity | user_selectivity
0.0012             | 0.9345

此时user_id更适合创建索引。

2.2 组合索引的排列艺术

正确的字段顺序可使索引效率提升10倍以上:

-- 电商订单查询场景
SELECT * FROM orders 
WHERE shop_id = 123 
  AND status = 3 
  AND create_time > '2023-01-01'
ORDER BY update_time DESC;

-- 最优索引方案:
ALTER TABLE orders ADD INDEX idx_shop_status_time (shop_id, status, create_time);

字段顺序遵循:等值查询字段 → 范围查询字段 → 排序字段。


3. 查询语句的调优实战

3.1 避免索引失效的六大陷阱

-- 错误示例1:隐式类型转换
SELECT * FROM users WHERE phone = 13800138000; -- phone是varchar类型

-- 错误示例2:索引列运算
SELECT * FROM products WHERE price*0.8 > 100;

-- 正确写法:
SELECT * FROM users WHERE phone = '13800138000';
SELECT * FROM products WHERE price > 100/0.8;

3.2 分页查询的优化方案

传统分页在大数据量时性能急剧下降:

-- 原始分页(100,000页开始)
SELECT * FROM articles 
ORDER BY create_time DESC 
LIMIT 100000, 20;

-- 优化方案:游标分页
SELECT * FROM articles 
WHERE create_time < '2023-06-01'  -- 记住上一页最后的时间
ORDER BY create_time DESC 
LIMIT 20;

4. 关联技术深度解析

4.1 覆盖索引的妙用

-- 原始查询(需要回表)
SELECT product_name, price FROM products 
WHERE category = 'electronics' 
  AND stock > 0;

-- 创建覆盖索引
ALTER TABLE products ADD INDEX idx_cover (category, stock, product_name, price);

覆盖索引可减少90%的I/O操作,但会增加索引存储空间。


5. 应用场景与技术选型

5.1 OLTP vs OLAP场景对比

场景类型 索引策略 典型查询特征
OLTP 精确索引+覆盖索引 高并发点查询
OLAP 位图索引+列式存储 复杂分析查询

5.2 不同存储引擎的差异

InnoDB与MyISAM的索引对比:

  • 聚簇索引结构差异
  • 锁机制对索引选择的影响
  • 事务支持与索引维护成本

6. 技术优缺点分析

6.1 B+树索引的优势

  • 范围查询高效
  • 自动平衡结构
  • 支持最左前缀匹配

6.2 索引的维护成本

  • 写操作性能损耗
  • 存储空间占用
  • 统计信息更新开销

7. 注意事项与最佳实践

  1. 定期使用ANALYZE TABLE更新统计信息
  2. 监控Handler_read_%状态变量
  3. 使用EXPLAIN FORMAT=JSON获取详细执行计划
  4. 避免在更新频繁的字段创建索引

8. 总结与展望

通过系统化的索引选择和查询优化,某金融系统将平均查询响应时间从320ms降至45ms。未来发展趋势包括:

  • 机器学习自动索引推荐
  • HTAP场景的混合索引策略
  • 新型存储引擎的索引优化