数据库性能优化实战

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


文章目录

    • [一、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

相关推荐
天桥下的卖艺者2 小时前
使用scitable包,两步生成逆概率删失权重(IPCW)
数据库·r语言
隔窗听雨眠2 小时前
AI原生数据库浪潮:国产数据库的架构重构与路径之争
数据库
数据库小学妹3 小时前
数据库选型实战:从数据类型到TCO成本,五维决策框架+九款产品横评
数据库·信创·国产数据库·数据库选型·oracle迁移
神龙天舞20014 小时前
MySQL 备库为什么会延迟好几个小时
android·数据库·mysql
丙氨酸長鏈5 小时前
Web前端入门第 问:JavaScript 一个简单的 IndexedDB 数据库入门示例
前端·javascript·数据库
独行侠影a6 小时前
APScheduler+Redis 分布式定时任务:解决多实例任务重复执行
数据库·redis·分布式
传说故事6 小时前
数据库中一些常用英文单词含义
数据库·oracle
夏贰四7 小时前
中小企业搭建业务中台如何控成本?业务中台轻量化落地分几步实施?
数据库·业务中台
林焱RPA7 小时前
影刀RPA200篇纪念版:最实用的20个自动化场景大盘点
数据库
名字还没想好☜7 小时前
Go 的 time.After 在 select 循环里内存泄漏:定时器堆积原理与 timer.Reset 正确姿势
java·数据库·golang·go·goroutine