MySQL 性能优化:从普通程序员的角度出发

326 阅读5分钟

前言

在业务开发和面试中,MySQL的优化是一个常见且重要的话题。本文将介绍几种常见的优化方式,涵盖多个方面, 优化是一个综合性的选择过程。
在实际工作中,不同开发者的职责和定位往往决定了无法全面进行优化。因此,本文主要从普通开发者的角度,分享一些能够实现的优化点。


优化方向

flowchart TD
    subgraph 优化方向
       direction TB

       架构优化
       连接配置优化
       数据表优化
		style 数据表优化 fill:#008000
       SQL语句优化
       style SQL语句优化 fill:#008000
       缓存优化
 		style 缓存优化 fill:#008000
       业务优化
		style 业务优化 fill:#008000
       硬件优化
    end

作为一名普通开发者来说,通常我们只用关注数据表优化SQL语句优化缓存优化业务优化。接下来,我主要从这四点展开详细说明。


1. 数据表优化

1.1. 选择合适的存储引擎

  • InnoDB:适合需要事务支持、外键约束和高并发的应用,比如电商网站的订单表。
  • MyISAM:适合只读查询多且不需要事务的场景,例如日志查询系统。

1.2. 使用索引

  • 单字段索引:查询条件仅涉及某个字段时,如WHERE user_id = ? 查询某个用户的所有订单。
  • 复合索引:查询条件包含多个字段时,如WHERE user_id = ? AND order_status = ? 查询某个用户的待付款订单。
  • 覆盖索引:查询只涉及索引字段时,如SELECT order_id, total_amount FROM orders WHERE user_id = ?,索引覆盖了查询的所有字段。

1.3. 分区表

  • 按时间范围分区:数据量非常大且按照时间查询较为频繁时,如日志表、订单表,按年份、月份、日等进行分区。
  • 按哈希分区:数据没有明确的时间或范围特征时,如用户信息表,使用哈希分区均匀分布数据。

1.4. 归档历史数据

  • 数据归档:对于不再频繁访问的历史数据,如超过一年以上的订单数据,考虑将其迁移到归档表中。

1.5. 表设计的范式化与反范式化

  • 范式化:数据高度结构化,且需要保证数据一致性时,如用户信息表、商品信息表等。
  • 反范式化:需要优化查询性能且读多写少时,如聚合统计表、分析报告表等。

2. SQL 语句优化

2.1. 优化查询

  • 避免SELECT *:查询大量数据时,确保只查询需要的字段,如SELECT order_id, total_amount FROM orders WHERE user_id = ?
  • 避免子查询:对于需要多次查询的场景,使用 JOIN 代替子查询,如SELECT * FROM orders JOIN users ON orders.user_id = users.user_id WHERE users.age > 30
  • 选择合适的索引:查询条件中涉及某个字段,如WHERE user_id = ?,使用单字段索引。
  • 多表查询时,尽量使用小表驱动大表
  • 减少不必要的 UNION 操作:查询时使用 UNION 操作可能导致性能下降,尽量用 JOIN 替代。
  • 避免使用 IN 查询:集合较大,可能导致性能下降。
  • 合理使用 LIMIT 和 OFFSET:分页查询时,使用 LIMITOFFSET 分页查询。
  • 批量操作时,尽量使用一条 SQL 语句
  • 使用 LIKE 时,注意索引的最左前缀原则,例如:LIKE '张三%'
  • 选择合适的排序方式:尽量避免不必要的排序,可以考虑使用索引支持排序。
  • 避免在 WHERE 子句中使用函数:如 WHERE DATE(field) = ?,尽量避免在查询中直接使用函数。
  • 选择合适的 JOIN 策略:根据数据量和查询条件,选择合适的 JOIN 策略,确保查询效率。
  • ...

3. 缓存优化

3.1. 查询缓存

使用场景
适用于经常重复执行的 SELECT 查询,能提高查询速度。

优点
缓存 SQL 结果集,减少重复查询的开销。

适用情况
查询结果比较稳定、返回数据量不大且频繁访问的场景。

注意事项
适用于结果集不经常变化的查询,可能因数据更新频繁导致缓存失效。
查询缓存在 MySQL5.7 版本之后已被推荐逐步弃用,建议谨慎使用。

3.2. 数据缓冲池

使用场景
适用于频繁读取的表和索引,提高整体查询性能。

优点
缓存表和索引的页数据,提升查询性能。

适用情况
用于经常读取表数据的应用,如 OLTP(在线事务处理)系统,特别是事务处理和读写混合应用。

优化建议

  • 调整innodb_buffer_pool_size:根据实际数据库大小和内存资源合理配置,提高数据缓存命中率。
  • 定期优化表:减少碎片,提高数据页的利用率。
  • 合适的索引使用:通过合适的索引提升缓存命中率。

3.3. 使用外部缓存

热点数据缓存
查询频繁的热点数据,如某个用户的订单信息,缓存到 Redis 或者一些其他缓存中,减少数据库压力。


4. 业务优化

4.1. 适当的建立冗余字段

  • 业务需求下,适当冗余一些字段到主表中,减少联查操作。

4.2. 高频查询的字段单独成表

  • 对于查询频繁的字段,单独成表,确保查询高效。

4.3. 事务控制优化

  • 合适地控制事务粒度,尽量减少事务范围,避免不必要的事务回滚。对于高并发场景,可以使用乐观锁(SELECT ... FOR UPDATELOCK IN SHARE MODE)来提高事务并发性。

4.4. 数据库表的分页查询

  • 针对分页查询,可以通过提前获取总数据量来优化分页性能。避免每次分页都进行全表扫描。

4.5. 确保业务逻辑和数据库操作分离

  • 避免在数据库中执行过多复杂的逻辑运算,适当利用应用层处理复杂逻辑,减轻数据库的计算负担。

结语

优化是一项持续的工作,MySQL的优化也不仅仅局限于这些方法。作为一名普通开发者,这些优化点已经足够我们在实际开发中应用,提升系统性能和响应速度。本次分享就到此结束了,希望这篇文章能帮助到你😁!