一文彻底弄懂MySQL的优化

news/2024/10/24 14:26:30/文章来源:https://www.cnblogs.com/lgx211/p/18499524

在企业级 Web 开发中,MySQL 优化是至关重要的,它直接影响系统的响应速度、可扩展性和整体性能。下面从不同角度,列出详细的 MySQL 优化技巧,涵盖查询优化、索引设计、表结构设计、配置调整等方面。

一、查询优化

1. 合理使用索引

  • 单列索引:为查询频繁的字段(如 WHEREORDER BYGROUP BY 中的字段)创建单列索引。
  • 组合索引:对于涉及多列条件的查询,建议使用组合索引。注意组合索引的顺序(最左前缀匹配原则)。
  • 覆盖索引:确保查询的字段全部被索引覆盖,这样 MySQL 可以直接从索引中获取数据,而无需访问表数据。
  • 避免过度索引:过多的索引会增加写操作的开销,如 INSERTUPDATEDELETE 操作,因为每次都要维护索引。

2. 优化查询语句

  • 避免使用 SELECT \*:明确选择需要的字段,避免多余的字段查询,减小数据传输量。
  • 避免在 WHERE 条件中对字段进行函数操作:如 WHERE YEAR(date_column) = 2023,这种操作会使索引失效,改为 WHERE date_column >= '2023-01-01' AND date_column < '2024-01-01'
  • 避免在 WHERE 条件中使用 OROR 会导致全表扫描,尽量使用 IN 或分解查询。
  • 尽量减少子查询:使用 JOIN 替代子查询。子查询会在嵌套时频繁执行,每次可能都会导致重新扫描表。
  • 合理使用 JOIN:如果有多表关联查询,确保关联的字段有索引,且表连接顺序要优化(小表驱动大表)。

3. 分页查询优化

  • 大数据分页:对于数据量非常大的分页查询,可以避免 LIMIT offset 方式,而是通过索引定位起始位置,例如 WHERE id > last_seen_id LIMIT 10
  • 减少数据扫描量:分页时不要 SELECT *,只选择主键字段返回结果后再根据主键查询详细信息。

4. 合理使用临时表和缓存

  • 复杂查询:对于复杂查询,可以先查询并存储到临时表中,再进行进一步查询操作,减少重复计算。
  • 缓存机制:在应用层或数据库层(如使用 Redis、Memcached)对频繁访问的数据做缓存,避免每次都查询数据库。

5. 避免死锁和锁等待

  • 减少锁范围:尽量让锁的范围小(如只锁定必要的行),避免表锁的使用。
  • 减少事务执行时间:事务越长,锁定的资源时间越长,容易导致锁等待甚至死锁。尽量减少事务中的查询或更新操作时间。

二、索引优化

1. 主键和唯一索引的合理使用

  • 主键索引:选择唯一且不变的字段作为主键,尽量使用自增整数主键,避免使用长字符串主键。
  • 唯一索引:在不允许重复值的字段上(如用户名、邮箱等)创建唯一索引,避免重复数据的插入。

2. 覆盖索引

  • 减少回表操作:对于查询涉及的字段全部在索引中时,MySQL 可以直接通过索引返回结果,避免回表查询。

3. 前缀索引

  • 长字符串字段的索引:对 VARCHAR 等长字符串类型字段建立索引时,可以使用前缀索引(如 CREATE INDEX idx_name ON users(name(10))),通过截取前几位字符来节省索引空间。

4. 避免冗余索引

  • 避免重复索引:例如已经有 (a, b) 组合索引时,不需要再单独给 a 建索引。
  • 索引维护:定期检查无用的索引(使用 SHOW INDEX FROM table_name)并删除,减少索引维护的开销。

三、表结构设计优化

1. 合理的表字段设计

  • 数据类型选择:选择最小且足够的字段类型。比如 INT(11) 占用 4 字节,如果值范围较小,可以使用 TINYINT(1 字节)、SMALLINT(2 字节)来节省空间。
  • 使用 VARCHAR 而非 CHARCHAR 为定长,存储固定长度字符会造成空间浪费,而 VARCHAR 为变长,适合存储不确定长度的字符串。
  • 避免使用 BLOB 和 TEXT 类型:大字段会造成性能问题,尽量将大文件或大数据放在文件系统中,数据库中仅存储文件路径。

2. 表分区

  • 水平分表:当表数据量过大(如上亿条记录)时,可以将表进行水平拆分,比如按照时间、用户ID等进行分表,减小单个表的大小。
  • 分区表:MySQL 提供表分区功能,可以根据数据范围将数据划分到不同的物理分区,优化大表查询性能。

3. 表规范化和反规范化

  • 表规范化:将数据分离到多个表中,避免数据冗余。数据量少时,范式化设计更易于维护。
  • 反规范化:当查询性能成为瓶颈时,可以考虑反规范化,增加冗余字段减少表的关联查询。

四、事务和锁机制优化

1. 减少锁竞争

  • 行锁优先:尽量避免使用锁范围更大的表锁,MySQL 的 InnoDB 引擎支持行锁,保证并发性。
  • 分批提交:批量操作数据时,可以将操作拆分成多个小批次提交,减少长时间锁持有。

2. 合理使用事务

  • 尽量减少事务时间:事务应尽可能短,避免长时间持有锁,导致资源被其他事务等待。
  • 事务隔离级别选择:根据业务需求选择合适的隔离级别,较高的隔离级别如 SERIALIZABLE 会有更多的锁定开销,常用的是 REPEATABLE READ

3. 使用乐观锁

  • 应用层乐观锁:对于并发更新的业务场景,可以在应用层使用版本号控制(乐观锁)来避免锁冲突。

五、配置优化

1. 调整 InnoDB Buffer Pool

  • Buffer Pool 的大小:InnoDB 的 Buffer Pool 用于缓存数据和索引,配置合理的缓存大小是优化 MySQL 性能的关键之一。建议 Buffer Pool 设置为物理内存的 70-80%。

    innodb_buffer_pool_size = 4G  # 根据内存大小调整
    

2. 查询缓存(Query Cache)

  • 关闭查询缓存:在 MySQL 5.7 及以后的版本,查询缓存功能逐渐被弃用,因为它在高并发场景下容易成为瓶颈。因此,建议将其关闭。

    query_cache_type = 0
    

3. 线程池优化

  • 调整连接线程:对于高并发的业务场景,可以调整 MySQL 的最大连接数(max_connections)和每个连接线程的最大数量。

    max_connections = 500
    

4. 磁盘 I/O 优化

  • 调整 innodb_flush_log_at_trx_commitinnodb_flush_log_at_trx_commit 控制日志何时写入磁盘。设置为 2 时,可以降低磁盘 I/O,提升性能,但会稍微增加数据丢失的风险。

    innodb_flush_log_at_trx_commit = 2
    

5. 调整日志文件大小

  • 设置合适的 redo log 大小innodb_log_file_size 配置 redo log 文件大小,建议根据写操作的频率和磁盘情况设置适合的大小,过小的 redo log 会频繁触发检查点,影响性能。

    innodb_log_file_size = 512M
    

6. 调整连接超时

  • 避免无效连接长时间占用:可以设置 MySQL 的连接超时参数,避免连接长时间闲置,造成资源浪费。

    wait_timeout = 600
    interactive_timeout = 600
    

六、监控与调优

1. 使用 EXPLAIN 分析查询

  • EXPLAIN 分析执行计划:通过 EXPLAIN 命令分析查询的执行计划,检查是否使用索引、扫描的行数等,优化 SQL 查询。

    EXPLAIN SELECT * FROM users WHERE name = 'Alice';
    

2. 慢查询日志

  • 开启慢查询日志:通过慢查询日志可以监控哪些查询执行时间过长,帮助定位性能瓶颈。

    slow_query_log = 1
    long_query_time = 2  # 设置为超过2秒的查询记录到日志
    

3. 数据库性能监控

  • MySQL Enterprise Monitor 或其他监控工具:使用监控工具跟踪数据库的整体性能指标,如 CPU、I/O、内存使用情况、查询响应时间、锁等待等,便于及时发现问题。

七、总结

MySQL 的性能优化需要从多个层面进行综合考虑:查询优化索引设计表结构设计事务控制配置调优等。在企业级 Web 开发中,不同业务场景下的优化需求有所差异,通常需要结合业务的实际需求做出合适的权衡。通过持续监控与调优,可以让 MySQL 数据库在高并发、大数据量的场景中保持高效稳定的性能。

来不及拥抱清晨,就已经手握黄昏。曾经的我苦苦找寻这份答案,如今已工作8年,已经是30岁的程序员了。时光流逝,白驹过隙,留给八年前的自己的答案。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/821186.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python C3算法

Python MRO C3算法是python当中计算类继承顺序的一个算法,从python2.3以后就一直使用此算法了。 c3 linearization算法称为c3线性化算法 C3算法原理 首先定义几个符号的意义:符号 意义L 针对一个类进行解析用L进行表示,例如L(A)表示对类A进行解析merge 合并操作的一个函数(…

我与信竞

抱歉,刚开始就要说再见了。抱歉,刚开始就要说再见了。 我从2020年开始学信竞,至今已有四年多了。 为何现在才开始写博客呢? 答曰:因为我要退役了。 10月26打CSP-S,不出意外的话,一切就快要结束了。 “历经艰辛的飞升者成了围剿孙悟空的十万天兵之一” ,是啊,这世上本不…

2024-10-24 main.js:6 Uncaught TypeError: app is not a function ==》写法错误

vue代码如下:// main.js import { createApp } from vue import ./style.css import App from ./App.vue const app = createApp(App);app().mount(#app)报错:原因:app().mount(#app)写法有误 正确写法应该去掉这个()import { createApp } from vue import ./style.css im…

Cinemachine系列——AimComposer

这个虚拟摄像机的瞄准算法会旋转摄像机,使其朝向指定的“注视”目标。同时,它还会应用偏移量、阻尼效果和构图规则。 主要要点: 朝向目标:摄像机会自动调整其方向,以面向指定的注视目标,例如角色的上脊椎或头骨、车辆,或通过程序控制或动画的虚拟对象。 偏移量:可以为摄…

Qt/C++路径轨迹回放/回放每个点信号/回放结束信号/拿到移动的坐标点经纬度

一、前言说明 在使用百度地图的路书功能中,并没有提供移动的信号以及移动结束的信号,但是很多时候都期望拿到移动的哪里了以及移动结束的信号,以便做出对应的处理,比如结束后需要触发一些对应的操作。经过搜索发现很多人都有这个需求,需要在js文件中加上一点代码才行,也就…

2024-2025-1 20241401 《计算机基础与程序设计》 第五周学习总结

班级链接 2024计算机基础与程序设计作业要求 第五周作业作业目标 ①Pep/9虚拟机 ②机器语言与汇编语言 ③算法与伪代码 ④测试:黑盒,白盒教材学习内容总结 《计算机科学概论》第六章计算机操作:介绍了计算机的基本操作,包括机器语言的基本概念。 机器语言是由一系列二进制代…

Thymeleaf基本使用

https://blog.csdn.net/weixin_45719444/article/details/122891930 介绍 官网:https://www.thymeleaf.org/ Thymeleaf是一个用于Web和独立环境的现代服务器端Java模板引擎。 简单示例打开IDEA,创建一个maven工程(quickstart archetype)。 在pom.xml文件中导入依赖,目前最…

漫谈自动化测试

前几天看到星球里几位同学在讨论各自所在团队的自动化测试实践案例和踩过的坑,蛮有意思的。 比如为了响应领导号召和满足绩效考核,搞各种各样的覆盖率指标;比如为了赶自动化测试覆盖率进度,每个接口和用例象征性的校验一下(甚至不校验不断言),各种各样意想不到的操作。 自…

AUTOSAR架构下,持续集成CI的最佳实践

随着汽车电子技术的快速发展,汽车软件的复杂性与日俱增,如何确保软件开发的高效性与稳定性成为了一个关键问题。为了解决这个问题,许多汽车企业和供应商逐渐引入了AUTOSAR架构,并在此基础上构建了持续集成(CI)流程。今天,我们就来探讨一下基于AUTOSAR架构的CI流程实践,…

哇!树链剖分(重链剖分学习笔记)

听说有人不会树链剖分? 前置芝士线段树 树状数组 Splay FHQ-Treap以上五种任意一种即可,这里主要讲线段树做法。 引入 树链剖分(Tree Line Pow Divide),一种解决树上快速路径修改查询问题的算法,一般指 重链剖分(Heavy Path Decomposition)。 思想图解 一个问题 如题,…

某SCADA系统发电机过速故障研究

某SCADA系统发电机过速故障研究 直观上讲,发电机转速过高故障最显然的特征应该就是“发电机转速”,因此对故障发生时的发电机转速进行可视化研究:如上图所示,对发电机转速进行了 Min-Max 归一化。该次故障报警时,确实存在转速较高的情况,但显然,并非转速高就会报警。通过…

CANOpen协议SDO中止报文(内存不足的解决方法)

今天在开发过程中,使用SDO进行字符串传输的时候出现了错误,检查到SDO服务器返回的报文帧是一个中止帧,中止代码为0x05040005这时候去翻CIA301的手册查中止代码的含义为内存不足经过断点调试跟踪,发现在config.h中是一个配置宏设置的是32,而我的字符串的长度为50,所以就中…