数据库性能调优的关键步骤
识别性能瓶颈
通过监控工具(如Prometheus、Datadog)或数据库内置工具(如MySQL的SHOW PROCESSLIST
、Oracle的AWR报告)分析慢查询、CPU/内存使用率、I/O等待时间。常见指标包括:
- 查询响应时间超过阈值(如>500ms)
- 锁等待时间过长
- 磁盘I/O饱和
优化查询语句
重写低效SQL,避免全表扫描和临时表。例如:
-- 优化前(未使用索引)
SELECT * FROM orders WHERE DATE(created_at) = '2023-01-01';
-- 优化后(利用索引)
SELECT * FROM orders WHERE created_at BETWEEN '2023-01-01 00:00:00' AND '2023-01-01 23:59:59';
使用EXPLAIN
分析执行计划,确保使用索引(type=ref
或range
),避免ALL
类型扫描。
索引策略优化
合理添加复合索引
根据高频查询条件组合创建索引。例如:
ALTER TABLE users ADD INDEX idx_name_email (last_name, email);
遵循最左前缀原则,避免冗余索引。
定期维护索引
删除未使用的索引(通过sys.schema_unused_indexes
检测),重建碎片化索引:
-- MySQL碎片整理
ALTER TABLE orders ENGINE=InnoDB;
-- PostgreSQL重建索引
REINDEX INDEX idx_order_date;
数据库配置调整
内存分配调优
- InnoDB缓冲池(MySQL):设置为可用内存的70-80%
innodb_buffer_pool_size = 12G
- 共享内存(PostgreSQL):
shared_buffers = 4GB effective_cache_size = 12GB
并发连接控制
限制连接数避免资源争用:
# MySQL
max_connections = 200
thread_cache_size = 32
# PostgreSQL
max_connections = 100
案例:电商平台订单查询优化
问题现象
高峰期订单查询延迟达2秒,数据库CPU使用率90%+。
解决方案
- 发现
orders
表的status
字段无索引,添加过滤索引:CREATE INDEX idx_orders_status ON orders(status);
- 优化联合查询,将OR条件改写为UNION:
-- 优化前 SELECT * FROM orders WHERE user_id=100 OR status='pending'; -- 优化后 SELECT * FROM orders WHERE user_id=100 UNION SELECT * FROM orders WHERE status='pending' AND user_id!=100;
- 调整InnoDB日志文件大小至1GB:
innodb_log_file_size = 1G
效果
查询延迟降至200ms内,CPU使用率下降至60%。
高级优化技术
分库分表
对单表数据量超过千万的表按时间或ID哈希拆分。例如:
-- 按月分表
CREATE TABLE orders_202301 (LIKE orders INCLUDING INDEXES);
读写分离
配置主从复制,将报表类查询路由到只读副本。
缓存层引入
对热点数据(如商品详情)使用Redis缓存,减少数据库访问:
# Python示例:先查缓存
def get_product(product_id):
data = redis.get(f"product:{product_id}")
if not data:
data = db.execute("SELECT * FROM products WHERE id=%s", product_id)
redis.setex(f"product:{product_id}", 3600, data)
return data