数据库性能优化实战

系列导读:本篇将深入讲解数据库性能优化的核心方法与实战技巧。


文章目录

    • [一、SQL 优化](#一、SQL 优化)
      • [1.1 慢查询分析](#1.1 慢查询分析)
      • [1.2 EXPLAIN 解读](#1.2 EXPLAIN 解读)
      • [1.3 优化原则](#1.3 优化原则)
    • 二、索引优化
      • [2.1 索引类型](#2.1 索引类型)
      • [2.2 索引设计原则](#2.2 索引设计原则)
      • [2.3 组合索引示例](#2.3 组合索引示例)
    • 三、架构优化
      • [3.1 读写分离](#3.1 读写分离)
      • [3.2 分库分表](#3.2 分库分表)
      • [3.3 缓存策略](#3.3 缓存策略)
    • 四、连接池优化
      • [4.1 HikariCP 配置](#4.1 HikariCP 配置)
      • [4.2 连接池监控](#4.2 连接池监控)
    • 总结

一、SQL 优化

1.1 慢查询分析

sql 复制代码
-- 开启慢查询日志
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 1;

-- 分析慢查询
EXPLAIN SELECT * FROM orders WHERE user_id = 100;

1.2 EXPLAIN 解读

字段 说明
type 访问类型(ALL/index/range/ref/const)
key 使用的索引
rows 扫描行数
Extra 额外信息

1.3 优化原则

sql 复制代码
-- 避免 SELECT *
SELECT id, name FROM users WHERE id = 1;

-- 避免函数操作
-- 差
SELECT * FROM orders WHERE DATE(create_time) = '2024-01-01';
-- 好
SELECT * FROM orders WHERE create_time >= '2024-01-01' AND create_time < '2024-01-02';

-- 避免 OR
-- 差
SELECT * FROM users WHERE name = '张三' OR age = 20;
-- 好
SELECT * FROM users WHERE name = '张三'
UNION
SELECT * FROM users WHERE age = 20;

-- 分页优化
-- 差
SELECT * FROM orders LIMIT 1000000, 10;
-- 好
SELECT * FROM orders WHERE id > 1000000 LIMIT 10;

二、索引优化

2.1 索引类型

类型 说明
主键索引 唯一、非空
唯一索引 唯一
普通索引 加速查询
组合索引 多列索引
全文索引 文本搜索

2.2 索引设计原则

复制代码
1. 选择区分度高的列
2. 遵循最左前缀原则
3. 覆盖索引减少回表
4. 控制索引数量
5. 避免冗余索引

2.3 组合索引示例

sql 复制代码
-- 组合索引
CREATE INDEX idx_user_status_time ON orders(user_id, status, create_time);

-- 命中索引
SELECT * FROM orders WHERE user_id = 1;
SELECT * FROM orders WHERE user_id = 1 AND status = 1;
SELECT * FROM orders WHERE user_id = 1 AND status = 1 AND create_time > '2024-01-01';

-- 不命中索引
SELECT * FROM orders WHERE status = 1;
SELECT * FROM orders WHERE create_time > '2024-01-01';

三、架构优化

3.1 读写分离

yaml 复制代码
# ShardingSphere 配置
spring:
  shardingsphere:
    datasource:
      names: master,slave
      master:
        type: com.zaxxer.hikari.HikariDataSource
        jdbc-url: jdbc:mysql://master:3306/mydb
      slave:
        type: com.zaxxer.hikari.HikariDataSource
        jdbc-url: jdbc:mysql://slave:3306/mydb
    rules:
      readwrite-splitting:
        data-sources:
          myds:
            write-data-source-name: master
            read-data-source-names: slave

3.2 分库分表

yaml 复制代码
# 分片配置
spring:
  shardingsphere:
    rules:
      sharding:
        tables:
          t_order:
            actual-data-nodes: ds${0..1}.t_order_${0..1}
            table-strategy:
              standard:
                sharding-column: order_id
                sharding-algorithm-name: order-inline

3.3 缓存策略

java 复制代码
// 缓存穿透防护
public User getUser(Long id) {
    String key = "user:" + id;
    User user = redisTemplate.opsForValue().get(key);
    
    if (user != null) {
        return user;
    }
    
    // 防止缓存穿透
    if (redisTemplate.hasKey("null:" + id)) {
        return null;
    }
    
    user = userMapper.selectById(id);
    
    if (user != null) {
        redisTemplate.opsForValue().set(key, user, 1, TimeUnit.HOURS);
    } else {
        // 空值缓存
        redisTemplate.opsForValue().set("null:" + id, "", 5, TimeUnit.MINUTES);
    }
    
    return user;
}

四、连接池优化

4.1 HikariCP 配置

yaml 复制代码
spring:
  datasource:
    hikari:
      minimum-idle: 10
      maximum-pool-size: 50
      idle-timeout: 600000
      max-lifetime: 1800000
      connection-timeout: 30000
      pool-name: OrderHikariPool

4.2 连接池监控

java 复制代码
// 获取连接池状态
HikariDataSource dataSource = (HikariDataSource) applicationContext.getBean(DataSource.class);
HikariPoolMXBean pool = dataSource.getHikariPoolMXBean();

log.info("活跃连接: {}", pool.getActiveConnections());
log.info("空闲连接: {}", pool.getIdleConnections());
log.info("等待线程: {}", pool.getThreadsAwaitingConnection());

总结

✅ SQL 优化 :慢查询、EXPLAIN、优化原则

✅ 索引优化 :类型、设计原则、组合索引

✅ 架构优化 :读写分离、分库分表、缓存

✅ 连接池优化:HikariCP 配置、监控


作者 :刘~浪地球
更新时间:2026-04-17

相关推荐
10年前端老司机1 小时前
Milvus 8种检索能力实践
数据库·python·agent
Decay__1 小时前
14_MySQL 高可用与容灾架构 —— MGR / InnoDB Cluster / Keepalived+VIP / 双主 / 读写分离 / 两地三中心
运维·数据库·sql·mysql·架构
freejackman1 小时前
【实战三】撕开脱敏盲区:深度解析 CASE WHEN 与窗口函数血缘
大数据·数据库·sql
codigger3 小时前
线上数据库连接池打满:从应急止损到架构根治的完整方案
数据库·sql·程序员
倔强的石头_3 小时前
集中式与分布式怎么选?我把手头11套系统重新过了一遍秤
数据库
挖掘狂人3 小时前
线上数据库连接池打满:从应急止损到架构根治的完整方案
数据库·sql·程序员
Rainmicro4 小时前
【无标题】
java·数据库·算法
Thanks_ks4 小时前
MySQL 的索引是什么?用图书馆的目录讲明白
数据库·sql·mysql·索引·联合索引·explain·慢查询优化
CoderYanger10 小时前
Java EE 进阶:8.MyBatis 操作数据库(入门)(第二弹)
java·数据库·spring boot·spring·面试·java-ee·mybatis
wafrdggh13 小时前
2026电商快递批量查询怎么用?固乔助手模板设置评测
大数据·数据库·小程序