Article

MySQL 数据库优化技巧总结

更新于:2024-11-10

引言

在学习数据库的过程中,我发现性能优化是一个非常重要的话题。本文总结了我学到的一些 MySQL 优化技巧。

索引优化

1. 合理使用索引

索引可以大大提高查询速度,但也会增加写入和更新的成本。

-- 创建单列索引
CREATE INDEX idx_username ON users(username);

-- 创建复合索引
CREATE INDEX idx_name_age ON users(name, age);

2. 避免索引失效

以下情况会导致索引失效:

  • 使用 !=<> 操作符
  • 使用 OR 连接条件
  • 在索引列上使用函数
  • 使用 LIKE 以通配符开头
-- ❌ 索引失效
SELECT * FROM users WHERE YEAR(created_at) = 2024;

-- ✅ 索引有效
SELECT * FROM users WHERE created_at >= '2024-01-01' 
AND created_at < '2025-01-01';

查询优化

1. 避免 SELECT *

只查询需要的列:

-- ❌ 不推荐
SELECT * FROM users WHERE id = 1;

-- ✅ 推荐
SELECT id, username, email FROM users WHERE id = 1;

2. 使用 LIMIT 限制结果

SELECT id, username FROM users 
WHERE status = 1 
ORDER BY created_at DESC 
LIMIT 10;

3. 优化 JOIN 查询

-- 使用 INNER JOIN 代替子查询
SELECT u.username, o.order_no
FROM users u
INNER JOIN orders o ON u.id = o.user_id
WHERE u.status = 1;

表设计优化

1. 选择合适的数据类型

  • 使用 INT 而不是 BIGINT(如果范围够用)
  • 使用 TIMESTAMP 而不是 DATETIME(节省空间)
  • 使用 ENUM 代替字符串(状态字段)
CREATE TABLE users (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) NOT NULL,
    status ENUM('active', 'inactive', 'banned') DEFAULT 'active',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

2. 表的垂直拆分

将不常用的大字段拆分到另一个表:

-- 主表
CREATE TABLE users (
    id INT PRIMARY KEY,
    username VARCHAR(50),
    email VARCHAR(100)
);

-- 扩展表
CREATE TABLE user_profiles (
    user_id INT PRIMARY KEY,
    bio TEXT,
    avatar_url VARCHAR(255),
    FOREIGN KEY (user_id) REFERENCES users(id)
);

配置优化

重要的配置参数

# my.cnf 配置文件

# 缓冲池大小(设置为物理内存的 50-80%)
innodb_buffer_pool_size = 4G

# 最大连接数
max_connections = 200

# 查询缓存(MySQL 8.0 已移除)
query_cache_size = 0

# 慢查询日志
slow_query_log = 1
long_query_time = 2

EXPLAIN 分析查询

使用 EXPLAIN 查看查询执行计划:

EXPLAIN SELECT * FROM users WHERE username = 'john';

重点关注的字段:

  • type: 连接类型(const > eq_ref > ref > range > index > all)
  • key: 使用的索引
  • rows: 扫描的行数
  • Extra: 额外信息

实战案例

案例:优化慢查询

问题查询

SELECT * FROM orders 
WHERE DATE_FORMAT(created_at, '%Y-%m') = '2024-11'
ORDER BY id DESC
LIMIT 10;

优化后

SELECT id, order_no, user_id, total_amount, created_at
FROM orders 
WHERE created_at >= '2024-11-01' 
AND created_at < '2024-12-01'
ORDER BY id DESC
LIMIT 10;

改进点

  1. 避免在索引列使用函数
  2. 只查询需要的字段
  3. 使用范围查询替代函数计算

监控工具

推荐使用的工具:

  • MySQL Workbench: 可视化管理工具
  • Percona Toolkit: 性能分析工具集
  • mysqldumpslow: 慢查询日志分析
  • pt-query-digest: 查询分析工具

学习总结

  1. 索引不是越多越好:需要权衡查询和写入性能
  2. 定期分析慢查询:找出性能瓶颈
  3. 合理的表设计:从一开始就要考虑优化
  4. 持续监控:使用工具监控数据库性能

参考资料


数据库优化是一个持续的过程,需要不断学习和实践!