MySQL 性能调优实战:索引优化、SQL 调优与分库分表策略

MySQL 性能调优实战:索引优化、SQL 调优与分库分表策略

Ethan
2025-05-10 发布 / 正在检测是否收录...

数据库性能问题是后端开发中最常见的瓶颈。然而,很多开发者的"优化"就是在字段上加个索引——然后发现还是慢。本文将系统梳理 MySQL 性能调优的三个核心维度:索引优化、SQL 调优和分库分表,并介绍 Druid 监控工具的使用。

索引优化的本质:数据结构的选择

B+Tree 为什么是 MySQL 的首选?

B+Tree 的所有数据都存在叶子节点,非叶子节点只存索引——这让单次磁盘 I/O 能检索更多索引键。在 16KB 的 InnoDB 页中,假设主键是 BIGINT(8字节)+ 指针(6字节),一个非叶子节点大约能存 16KB / 14B ≈ 1170 个索引键。三层 B+Tree(根→中间→叶子)约能索引 1170 × 1170 × 16 ≈ 两千万行。这意味着绝大多数 OLTP 查询只需 1~3 次磁盘 I/O。

最左前缀原则:面试必问

CREATE INDEX idx_a_b_c ON users(a, b, c);

-- 走索引(匹配最左前缀)
SELECT * FROM users WHERE a = 1;
SELECT * FROM users WHERE a = 1 AND b = 2;

-- 不走索引(跳过了 a)
SELECT * FROM users WHERE b = 2;
SELECT * FROM users WHERE c = 3;

-- 部分走索引(a 走索引,c 不走)
SELECT * FROM users WHERE a = 1 AND c = 3;

索引失效的常见场景

-- 1. 函数操作(索引列参与计算)
SELECT * FROM orders WHERE DATE(create_time) = '2025-01-01';  -- 失效!
-- 改为:WHERE create_time >= '2025-01-01' AND create_time < '2025-01-02';

-- 2. 隐式类型转换
SELECT * FROM users WHERE phone = 13800138000;  -- phone 是 VARCHAR,失效!

-- 3. LIKE 前置模糊
SELECT * FROM articles WHERE title LIKE '%MySQL%';  -- 完全失效

-- 4. OR 条件不全有索引
SELECT * FROM users WHERE name = 'ABC' OR age = 25;  -- age 没有索引

覆盖索引:最优雅的性能优化

CREATE INDEX idx_name_age ON users(name, age);
SELECT name, age FROM users WHERE name = 'ABC';  -- 不需要回表!

SQL 执行计划分析(EXPLAIN 必看项)

EXPLAIN SELECT * FROM orders WHERE user_id = 100 AND status = 'paid';

-- 关键指标
-- type:  const > eq_ref > ref > range > index > ALL(绝对不能出现 ALL)
-- key:   实际使用的索引
-- rows:  扫描行数(越小越好)
-- Extra: Using filesort / Using temporary(出现就说明需要优化)

慢查询分析:找到瓶颈

-- 开启慢查询日志
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 1;

-- 用 mysqldumpslow 分析
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log

Druid SQL 监控

// Spring Boot 集成 Druid
spring:
  datasource:
    druid:
      stat-view-servlet:
        enabled: true
        url-pattern: /druid/*
        login-username: admin
        login-password: admin
      filter:
        stat:
          enabled: true
          slow-sql-millis: 1000
          log-slow-sql: true

通过 /druid/index.html 可视化查看:SQL 执行次数、耗时分布、连接池状态、慢查询列表。

分库分表策略

垂直分库:按业务拆分

用户库(user_db)、订单库(order_db)、商品库(product_db),各库独立部署、独立扩容。

水平分表:ShardingSphere-JDBC 配置

# sharding.yml
rules:
  - !SHARDING
    tables:
      t_order:
        actualDataNodes: ds0.t_order_$->{0..15}
        databaseStrategy:
          standard:
            shardingColumn: user_id
            shardingAlgorithmName: db_inline
        tableStrategy:
          standard:
            shardingColumn: order_id
            shardingAlgorithmName: order_inline
    shardingAlgorithms:
      db_inline:
        type: INLINE
        props:
          algorithm-expression: ds$->{user_id % 2}
      order_inline:
        type: INLINE
        props:
          algorithm-expression: t_order_$->{order_id % 16}

总结

MySQL 优化有一个优先级:SQL 优化 > 索引优化 > 架构优化。大多数性能问题的根源在于糟糕的 SQL 和缺失的索引,而不是"数据库配置参数不够好"。Druid 监控是你发现这些问题的眼睛,而分库分表是最后的底牌——在此之前,请先确保 SQL 和索引已经做到最好。

© 版权声明
THE END
喜欢就支持一下吧
点赞 1 分享 收藏

评论 (0)

取消

Warning: file_put_contents(/var/www/html/usr/cache/pagecache/93/9392d411f5525366d26d035eee46aa85.cache): failed to open stream: No such file or directory in /var/www/html/usr/plugins/PageCache/Plugin.php on line 188