MYSQL-8.调优

news2024/12/24 8:09:22

性能优化思维

整体思维

  1. 木桶效应:系统的性能符合木桶效应(一个木桶能装多少水,取决于木桶中最短的那块木板),所以性能优化需要从多个方面去考虑,如架构优化、业务优化、前端优化、中间件调优、网关优化、JVM优化、数据库优化、代码优化、容器/硬件优化等;
  2. 优化分类
    1. 架构优化:从系统整体架构考虑,如:读写分离、集群部署、引入缓存/搜索/消息中间件、中台架构、分库分表等;
    2. 参数优化:从系统组件方面考虑,如:JVM、服务器、数据库、中间件、网关、容器等组件的参数调整;
    3. 代码优化:从代码方面考虑,如:代码中采用更优秀的算法思想/设计模式、SQL优化、对中间件的操作优化等;

单个服务层面

  1. 在程序中,业务的执行实体都是线程,所以程序的性能一般与线程挂钩;
    1. CPU、内存、磁盘等硬件资源:线程最终会由CPU进行调度(时间片轮训)执行,且在线程的执行过程也必然需要对数据进行操作(绝大部分的业务本质都是对数据的CURD)最终都是与内存、磁盘打交道;

      1. 关联:线程越多,需要的CPU调度能力也就越强,需要的内存也越大,磁盘IO速率也会要求越快,当三者之间任意一个达到了瓶颈,程序中的线程数量也会达到极限,达到极限后,系统的性能会成抛物线式下滑,从而可能导致系统整体性能下降乃至瘫痪;
        所以一般不能让CPU、内存、磁盘等资源的使用率达到95%+,最大利用率控制在80-85%左右为最佳状态。
  2. 线程工作模型:程序设计中主要存在三种线程处理模型:BIO、NIO、AIO;可以参考;
    1. BIO阻塞IO模型:BIO是最传统的一对一处理模型,也就是一个客户端请求分配一条线程处理;
    2. NIO非阻塞IO模型:NIO的最佳实践为reactor模型;
    3. AIO异步IO模型:AIO落地实现proactor模型;

架构层面

  1. 优秀且合适的架构胜过多次调优:一个使用Tomcat+MySQL部署的系统,无论如何调优都无法处理万级并发;
  2. 架构需要符合实际业务,没有完美的架构只有最合适的架构,从现有环境及实际业务出发,选用最为合适的技术体系,这才是我们应该做的事情。如:
    1. 项目业务中读写参半,单节点难以承载压力,可以考虑项目集群、双主热备值等;
    2. 项目业务中写大于读,可以考虑引入消息中间件、DB分库、项目集群等;
    3. 项目业务中读大于写,可以考虑引入缓存/搜索中间件、动静分离、读写分离等;
  3. 架构可以进一步优化,当系统原有架构遇到性能瓶颈时,可以考虑进一步做架构优化,如:设计多级分布式缓存、缓存中间件做集群、消息中间件做集群、Java程序做集群、数据库做分库分表、搜索中间件做集群等,随着引入的技术越多,系统会越庞大,需要考虑的问题也会更加棘手,但带来的性能提升也是显著的;

预防大于解决

  1. 当问题在出现时再想办法解决,这是一种下下策,防范于未然才是最佳方案
  2. 项目初期:在项目初期,我们应该对未来的流量压力、数据大小等进行预测,提前根据业务和设计出合适的架构,确保上线后可以承载业务的正常压力和增长;不要“卡点”设计,也不能过度设计造成性能过剩
  3. 项目上线后:计划赶不上变化,项目初期的预测难免会出现偏差,一套完善的监控系统,在性能瓶颈来临前设好警报线,确保能够在真正的性能瓶颈到来之前解决问题;

性能调优的核心步骤

通常而言,性能优化的步骤可分为如下几步:

  1. 发现性能瓶颈:如有监控系统,那它会主动发出警报;如若没有,那出现瓶颈时应用肯定会出问题,如:无响应、响应缓慢、频繁宕机等。
  2. 排查瓶颈原因:排查瓶颈是由于故障问题导致的,还是真的存在性能瓶颈。
  3. 定位瓶颈位置:往往一个系统都会由多个层面协同工作,然后对外提供服务,当发现性能瓶颈时,应当确定瓶颈的范围,如:网络带宽瓶颈、Java应用瓶颈、数据库瓶颈等。
  4. 解决性能瓶颈:定位到具体的瓶颈后对症下药,从结构、配置、操作等方面出发,着手解决瓶颈问题。

Mysql性能优化

一般分为五个维度

客户端与连接层优化

调整客户端DB连接池参数和DB连接层参数;

  1. 客户端的连接池大小设置可以参考PostgreSQL的计算公式:最大连接数 = (CPU核心数 x 2) + 有效磁盘数(SSD固态硬盘数量)
    1. 为什么不限制服务端连接数MySQL实例一般情况下只为单个项目提供服务,应用程序的连接数做了限制,自然也就限制了服务端的连接数;
    2. 正常来说MySQL的最大连接数应大于客户端连接池的最大连接数,存在通过终端工具远程连接MySQL等情况,如果设置一致就很有可能导致MySQL连接数爆满;
    3. 对于最佳连接数的计算,首先要把CPU核数放首位考虑,紧接着是磁盘,最后是网络带宽,因为带宽会影响SQL执行时间,综合考虑后才能计算出最合适的连接数大小
  2. 偶发高峰类业务的连接数配置:在某些时间段或者活动开始时,流量会高于平时流量,可以将常驻连接数配成CPU核数+1,同时缩短连接的存活时间,及时释放空闲的数据库连接;
  3. mysql最大连接数设置set max_connections = n;

Mysql参数优化:

  1. 设置方式:启动之后通过set global @@xxx = xxx的方式调整,但最好还是直接修改my.ini/my.conf配置文件;
  2. InnoDB缓冲区配置innodb_buffer_pool_size一般为内存的70%~80%
    1. 实例空间:当InnoDB的缓冲区空间大于1GB时,会自动划分多个实例空间,可以在多线程并发执行时,减少并发冲突,MySQL官方的建议是每个缓冲区实例须大于1GB,通过innodb_buffer_pool_instances设置;
  3. 工作线程缓冲区配置最好根据机器内存设置为一到两倍MB大小
    1. sort_buffer_size排序缓冲区大小,影响group by、order by...等排序操作。
      1. max_length_for_sort_data:如果排序字段值的最大长度小于该值,则会将所有要排序的字段值载入内存排序,但如果大于该值时,则会一批一批的加载排序字段值进内存,然后一边加载一边做排序
    2. read_buffer_size读取缓冲区大小,影响select...查询操作的性能。
    3. join_buffer_size联查缓冲区大小,影响join多表联查的性能。
  4. 调整临时表空间tmp_table_size、max_heap_table_size两个参数主要是限制临时表可用的内存空间,当创建的临时表空间占用超过tmp_table_size时,就会将其他新创建的临时表转到磁盘中创建;
    1. 参数大小:可以根据show global status like 'created_tmp%';统计信息决定Created_tmp_disk_tables / Created_tmp_tables * 100% = 120%
  5. 调整空闲线程的存活时间
    1. 查看数据库连接峰值show global status like 'Max_used_connections';
    2. 空闲连接的超时时间wait_timeout、interactive_timeout默认八小时也就是一个连接断开后,默认也会将对应的工作线程缓存八小时后再销毁,这里我们可以手动调整成30min~1h左右,可以让无用的连接能及时释放,减少资源的占用。

编码层面优化:

  1. 编写sql时需考虑sql是否走索引,可以参考索引使用;

  2. 查询时尽量按需取字段,避免使用*

    1. 当使用*时,解析器需要先去解析出当前要查询的表上*表示哪些字段,因此会额外增加解析成本;
    2. InnoDB会将查询的结果放入缓存中,查询的字段越多结果集也就越大占用的内存也会越大,所存储的其他数据也就越少,当其他SQL操作时,在内存中找不到数据,又会去触发磁盘IO,最终导致MySQL整体性能下降;
  3. 尽量将大事物拆分成小事物;

    1. 当事物较大且包含写事物时,会导致一部分数据长时间锁定,从而可能引起大量事物出现阻塞;
    2. 大事务也会导致日志写入时出现阻塞,这种情况下会强制触发刷盘机制,大事务的日志需要阻塞到有足够的空间时,才能继续写入日志到缓冲区,这也可能会引起线上出现阻塞,可通过show status like 'innodb_log_waits';查看是否有大事务由于redo_log_buffer不足,而在等待写入日志。
  4. 尽量避免深分页的情况select * from test limit 100000,10在MySQL的实际执行过程中,首先会查询出100010条数据,然后丢弃掉前面的10W条数据,将最后的10条数据返回;

    1. 解决办法:基于递增连续字段

      -- 第一页
      select * from test where 有序字段 >= 1 limit 10; 
      -- 第二页
      select * from test where 有序字段 >= 11 limit 10;
      
  5. 避免循环调用sql,新增和更新最好采用批量操作,查询可以先将所需数据查询出来建立映射关系;

多表连接查询

  1. 避免三表以上的连表查询,且要以小表驱动大表,原因是:连表查询的数据量是各表数据的笛卡尔积,会随着表数据增加累乘增加;

  2. 关联算法MySQL8.0之前的关联算法为Nest Loop Join嵌套循环连接算法,该算法会依照驱动表的结果集作为循环基础数据,然后通过该结果集中一条条数据,作为过滤条件去下一个表中查询数据,最后合并结果得到最终数据集;

    1. 优化器的选择逻辑:如果指定了连接条件,满足查询条件的小数据表作为驱动表。如果未指定连接条件,数据总行数少的表作为驱动表。

    2. 优化器不一定能够正确选择,最好在编写sql时考虑好;假设有a(1000条数据)、b(10条数据)两张表,select * from a as t1 left join b as t2 on t1.id = t2.id;会循环1000次查询数据,而select * from b as t1 left join a as t2 on t1.id = t2.id;只需要循环十次;

      // 伪逻辑
      for(数据 x : 驱动表){
          for(数据 y : 被驱动表){
              if (x == y){
                  // 如果符合连接条件,则记录到连接查询的结果集中.....
              }
          }
      }
      
  3. 哈希连接(Hash Join) Mysql8.0新增,对连表时存在等值连接条件且未命中索引的情况下的连接查询优化:

    在这里插入图片描述

    // 伪代码
    // 构建阶段:将小表的每行数据,根据哈希值放入内存哈希表中
    Map hashTable = new HashMap();
    for(数据 x : 构建表){
        hashTable.put(x);
    }
    
    // 探测阶段:遍历大表的每行数据与内存哈希表做连接匹配
    for(数据 y : 探测表){
        if (hashTable.get(y) != null){
            // 如果哈希处理后能够在内存哈希表中存在,
            // 则表示这条数据符合连接条件,则记录到连接查询的结果集中.....
        }
    }
    
    1. 分为两个阶段:
      1. 构建阶段:选择一张小表为构建表,然后基于连接字段做哈希处理,接着将生成的哈希值放入内存中构建出一张哈希表
      2. 探测阶段遍历大表的每一行数据,然后对连接字段做哈希处理,通过生成的哈希值与内存哈希表做比较,将符合条件的数据放入结果集;
    2. 相对于嵌套循环性能的提升:
      1. 对于大表只需要遍历一次,而嵌套循环需要遍历N次;
      2. 在探测阶段时,只需要先对数据做一次哈希处理,复杂度为O(1), 而循环连接为O(n);
    3. 存在的问题:
      1. 内存中的join_buffer_size的大小可能无法完全载入哈希表;解决办法:
        • 分批处理:在构建阶段将构建表的数据进行拆分,在探测阶段每次载入一部分到内存中,这样会导致遍历次数增多;
        • 磁盘+内存混合处理:将内存中放不下的数据放入磁盘,在探测阶段遍历大表判断时,从磁盘依次读入处理好的哈希值进行判断;
      2. Mysql采用的是磁盘+内存混合处理的方式;
    4. 使用限制:
      1. 仅支持内连接的多表连接查询;
      2. 必须要去等值连接查询条件;
      3. 连接字段可走索引的情况下,默认依旧会采用循环连接算法;
    5. 默认开启,可通过set optimizer_switch="hash_join=off";命令控制;
  4. 反连接(Anti Join) Mysql8.0新增,对与一些反范围查询操作的优化

    1. 优化场景:
      1. NOT IN (SELECT … FROM …)
      2. NOT EXISTS (SELECT … FROM …)
      3. IN (SELECT … FROM …) IS NOT TRUE
      4. EXISTS (SELECT … FROM …) IS NOT TRUE
      5. IN (SELECT … FROM …) IS FALSE
      6. EXISTS (SELECT … FROM …) IS FALSE

Mysql结构优化:

  1. 表结构优化:字段数量不能过多、主键最好自增、根据业务建立中间表等;
  2. 字段结构优化:在保证足够使用的范围内,选择最小数据类型;尽量避免NULL值等;
  3. 索引结构优化:参考之前的索引使用

整体架构优化:

  1. 引入缓存中间件解决读压力
    1. 优点:在设置合理的情况下,可以为Mysql分担70%以上的读压力;
    2. 缺点:系统变复杂,需要考虑缓存击穿、缓存穿透、缓存雪崩、数据一致性等问题
  2. 引入消息中间件解决写压力;
    1. 优点:利用了MQ流量削峰的能力,使请求平滑的到达数据库;
    2. 缺点:数据库数据存在一定的延时;
  3. 主从读写分离,适用于读多写少业务,提高mysql自身抗压能力;
    1. 优点:通过搭建集群,提高了mysql的抗压能力;
    2. 缺点:主节点和从节点之间存在数据不一致的情况;
  4. 双主双写热备,适用于写多读少的情况
    1. 需要考虑自增ID问题;
  5. 分库分表,规避存储容量的上限+木桶效应

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一般产品:功能、质量、结构

**一般产品:**功能、质量、结构 通用工程: 收益-风险;过程-结果;少数-多数 风险 vs 收益 过程 vs 结果 少数 vs 多数 工程师的特点: 人道无害雇主实事求是,恪守公心,严守纪律,…

LeetCode-460. LFU 缓存【设计 哈希表 链表 双向链表】

LeetCode-460. LFU 缓存【设计 哈希表 链表 双向链表】 题目描述:解题思路一:一张图秒懂 LFU!解题思路二:精简版!两个哈希表,一个记录所有节点,一个记录次数链表【defaultdict(new_list)&#x…

ChatGLM3大模型本地化部署、应用开发与微调

文章目录 写在前面ChatGLM3推荐图书作者简介推荐理由粉丝福利写在后面 写在前面 本期博主给大家推荐一本初学者学习并部署大模型的入门书籍,一起来看看吧! ChatGLM3 ChatGLM3是继一系列先进语言模型之后的又一力作,专为追求高精度和广泛适…

Linux网络——自定义序列化与反序列化

前言 之前我们学习过socket之tcp通信,知道了使用tcp建立连接的一系列操作,并通过write与read函数能让客户端与服务端进行通信,但是tcp是面向字节流的,有可能我们write时只写入了部分数据,此时另一端就来read了&#x…

【Linux】进程间通信方式之管道

🤖个人主页:晚风相伴-CSDN博客 💖如果觉得内容对你有帮助的话,还请给博主一键三连(点赞💜、收藏🧡、关注💚)吧 🙏如果内容有误的话,还望指出&…

阿里云开发uniapp之uni-starter

一、为什么使用uni-starter uni-starter是集成商用项目常见功能的、云端一体应用快速开发项目模版。 一个应用有很多通用的功能,比如登录注册、个人中心、设置、权限管理、拦截器、banner... uni-starter将这些功能都已经集成好,另外,uni-s…

Linux下的SPI通信

SPI通信 一. 1.SPI简介: SPI 是一种高速,全双工,同步串行总线。 SPI 有主从俩种模式通常由一个主设备和一个或者多个从设备组从。SPI不支持多主机。 SPI通信至少需要四根线,分别是 MISO(主设备数据输入,从设备输出),MOSI (主设数据输出从设备输入),SCLK(时钟信号),CS/SS…

ARM(4)缓存一致性

目录 一、缓存一致性问题 二、一致性实现方案 2.1 目录一致性协议 2.2 嗅探一致性协议 三、CHI协议 3.1 cache state 3.2 snoop维护一致性 四、其他一致性协议 4.1 MSI协议 4.2 MESI 协议 4.3 MOESI协议 本文介绍以下内容: 缓存一致性问题一致性实现方案…

vCenter 7.3证书过期无法登录处理方法

登录报错:如下图 Exception in invking authentication handler [SSL: CERTIFICATE_VERIFY_FAILED] certificate vertify failed: certificate has expired(_ssl.c:1076) 处理方法1:推荐,可行 登录vCenter控制台,AltF3切换至命令…

【DFT】高 K/金属栅极阈值电压偏移的密度泛函模型

文章《Density functional model of threshold voltage shifts at High-K/Metal gates》,是由R. Cao、Z. Zhang、Y. Guo、J. Robertson等人撰写,发表在《Solid-State Electronics》期刊上。通过密度泛函理论(Density Functional Theory, DFT&…

....comic科学....食用手册....

1.点击链接后,保存漫画至夸克网盘,若是新用户需要用手机注册. 2.在应用商店下载夸克APP. 3.登录APP下载已保存的漫画. 3.1 进入APP点击 夸克网盘 3.2 点击“转存的内容”后,长按 漫画文件夹,点击下载,下载速度400K左…

树(数据结构)

树的定义 一个根结点,其余结点分为 m 个不相交的集合, 其中每个集合本身又是一棵树,并且称为根的子树。 树的根结点没有前驱,其他结点有且仅有一个前驱。 所有结点可以有0个或多个后继。 基本术语 结点的度 树的度 : 树…

【Linux】深浅睡眠状态超详解!!!

1.浅度睡眠状态【S】(挂起) ——S (sleeping)可中断睡眠状态 进程因等待某个条件(如 I/O 完成、互斥锁释放或某个事件发生)而无法继续执行。在这种情况下,进程会进入阻塞状态,在阻塞状态下,进程…

mac 本地使用docker 运行es,kibana

1.下载 m芯片一些版本不支持.踩过坑.翻看官网才知道只有部分镜像支持m芯片 https://hub.docker.com/添加链接描述 docker pull elasticsearch:7.17.21 docker pull kibana:7.17.21镜像已经下载下来了 2.创建文件映射-挂载 /Users/lin/dev/dockerMsg 其中lin是自己的用户名…

设计模式(2)——工厂方法模式

目录 1. 摘要 2. 需求案例(设计一个咖啡店的点餐系统) 2.1 咖啡父类及其子类 2.2 咖啡店类与咖啡类的关系 3. 普通方法实线咖啡店点餐系统 3.1 定义Coffee父类 3.2 定义美式咖啡类继承Coffee类 3.3 定义拿铁咖啡继承Coffee类 3.4 定义咖啡店类 3.5 编写测试类 4. 简…

大模型微调实战之强化学习 贝尔曼方程及价值函数(五)

大模型微调实战之强化学习 贝尔曼方程及价值函数(五) 现在, 看一下状态-动作值函数的示意图: 这个图表示假设首先采取一些行动(a)。因此,由于动作(a),代理可能会被环境转换到这些状…

docker Harbor私有仓库部署管理

搭建本地私有仓库,但是本地私有仓库的管理和使用比较麻烦,这个原生的私有仓库并不好用,所以我们采用harbor私有仓库,也叫私服,更加人性化。 一、什么是Harbor Harbor是VWware 公司开源的企业级Docker Registry项…

ESP8266-01s刷入固件报SP8266 Chip efuse check error esp_check_mac_and_efuse

一、遇到的问题 使用ESP8266 固件烧录工具flash_download_tools_v3.6.8 烧录固件报错: 二、解决方法 使用espressif推出发基于python的底层烧写工具:esptool 安装方法:详见https://docs.espressif.com/projects/esptool/en/latest/esp32/ …

腾讯游戏海外扩张,增持芬兰游戏开发商股份持股比例增至14.8%

易采游戏网5月8日消息,近日腾讯再次出手,大幅增持了芬兰知名游戏开发商Remedy Entertainment的股份,持股比例猛增至14.8%。这一举动引起了业界和投资者的广泛关注。 据了解,腾讯此次增持是在2024年4月24日完成的。根据芬兰法律规…

Pandas高效化运算与时间序列处理

文章目录 第1关:字符串操作方法第2关:Pandas的日期与时间工具第3关:Pandas时间序列的高级应用 第1关:字符串操作方法 任务描述 本关任务:读取step1/bournemouth_venues.csv文件,获取Venue Name列&#xff…