高并发读取场景下,MySQL的读请求量往往会达到每秒数千甚至上万次,不合理的配置和设计会导致查询耗时增加、数据库CPU和IO负载飙升,最终影响业务正常开展。优化读性能需要从多个层面逐步推进,结合业务特性选择适配的方案。

索引层面优化
索引是提升读性能最直接的方式,不合理的索引设计反而会降低性能,需要遵循以下原则:
- 优先为高频查询的where条件、join关联字段、order by和group by字段创建索引
- 避免创建冗余索引,定期清理未被使用的无用索引
- 控制索引长度,过长的索引会占用更多存储空间,降低查询效率
- 联合索引遵循最左前缀原则,将区分度高的字段放在前面
查看索引使用情况的SQL语句如下:
-- 查看指定表的索引信息 SHOW INDEX FROM user_order; -- 查看冗余索引,需要开启sys库 SELECT * FROM sys.schema_redundant_indexes;
查询语句优化
低效的查询语句即使有索引也无法发挥最大作用,优化查询可以从以下方向入手:
避免全表扫描
尽量不要使用SELECT *,只查询需要的字段,减少数据传输和IO消耗。同时避免在where条件中对字段进行函数操作或者类型转换,这会导致索引失效。
错误示例:
-- 对create_time做函数处理,索引失效 SELECT id FROM order_info WHERE DATE(create_time) = '2024-05-01';
正确示例:
-- 范围查询可以使用索引 SELECT id FROM order_info WHERE create_time >= '2024-05-01 00:00:00' AND create_time < '2024-05-02 00:00:00';
优化分页查询
深度分页场景下,LIMIT 100000, 10这类语句会扫描大量无用数据,性能很差。可以改用基于主键的游标分页方式:
-- 假设上次查询的最大id是100000,查询下一页数据 SELECT id, order_no FROM order_info WHERE id > 100000 ORDER BY id LIMIT 10;
缓存策略应用
对于重复度高的读请求,引入缓存可以减少MySQL的直接访问压力:
- 应用层缓存:使用Redis等缓存中间件,将高频查询的结果缓存起来,设置合理的过期时间,缓存命中时直接返回结果
- MySQL查询缓存:低版本MySQL可以开启查询缓存,但注意频繁更新的表不适合开启,高版本MySQL已经移除了查询缓存功能
简单的Redis缓存实现示例(Java语言):
public OrderInfo getOrderById(Long orderId) {
// 先从Redis查询缓存
String cacheKey = "order:" + orderId;
String cacheValue = redisTemplate.opsForValue().get(cacheKey);
if (cacheValue != null) {
return JSON.parseObject(cacheValue, OrderInfo.class);
}
// 缓存未命中,查询数据库
OrderInfo order = orderMapper.selectById(orderId);
if (order != null) {
// 缓存结果,设置30分钟过期
redisTemplate.opsForValue().set(cacheKey, JSON.toJSONString(order), 30, TimeUnit.MINUTES);
}
return order;
}
数据库架构调整
当单库读压力无法通过上述方式缓解时,可以调整数据库架构:
- 读写分离:搭建一主多从架构,写请求走主库,读请求分摊到多个从库,提升整体读吞吐量
- 分库分表:如果单表数据量过大,可以对大表进行水平拆分,减少单表数据量,提升查询效率
- 使用连接池:合理配置数据库连接池参数,避免频繁创建销毁连接带来的性能损耗
读写分离场景下,应用层可以通过注解指定读请求走从库,示例(Spring Boot + ShardingSphere):
@Service
public class OrderService {
@Autowired
private OrderMapper orderMapper;
// 读操作,默认走从库
public OrderInfo getOrder(Long orderId) {
return orderMapper.selectById(orderId);
}
// 写操作,走主库
@Transactional
public void createOrder(OrderInfo order) {
orderMapper.insert(order);
}
}
参数配置调优
合理的MySQL参数配置也能提升读性能,常用的调优参数如下:
| 参数名 | 说明 | 建议值 |
|---|---|---|
| innodb_buffer_pool_size | InnoDB缓冲池大小,用于缓存数据和索引 | 物理内存的50%-70% |
| query_cache_size | 查询缓存大小(低版本适用) | 根据业务情况设置,不建议过大 |
| max_connections | 最大连接数 | 根据业务并发量设置,避免过小导致连接拒绝 |
| sort_buffer_size | 排序缓冲区大小 | 根据排序场景调整,不建议全局设置过大 |
修改参数后需要重启MySQL服务生效,部分动态参数可以通过SET GLOBAL命令临时修改。
性能监控与验证
优化完成后需要通过监控验证效果,常用的监控指标包括:
- 查询平均耗时:通过慢查询日志和监控工具查看优化前后的耗时变化
- QPS:每秒查询量,优化后读QPS应该有明显提升
- 数据库负载:CPU、IO使用率应该有所下降
开启慢查询日志的配置示例:
-- 开启慢查询日志 SET GLOBAL slow_query_log = 'ON'; -- 设置慢查询阈值,单位秒,超过该时间的查询会被记录 SET GLOBAL long_query_time = 1; -- 查看慢查询日志文件路径 SHOW VARIABLES LIKE 'slow_query_log_file';