广告
返回顶部
首页 > 资讯 > 数据库 >MySQL中的SQL优化实战记录
  • 801
分享到

MySQL中的SQL优化实战记录

2024-04-02 19:04:59 801人浏览 薄情痞子
摘要

这篇文章主要介绍“Mysql中的sql优化实战记录”,在日常操作中,相信很多人在mysql中的SQL优化实战记录问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”MySQL中的S

这篇文章主要介绍“Mysql中的sql优化实战记录”,在日常操作中,相信很多人在mysql中的SQL优化实战记录问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”MySQL中的SQL优化实战记录”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

背景

本次SQL优化是针对javaweb中的表格查询做的。

部分网络架构图

MySQL中的SQL优化实战记录

业务简单说明

N个机台将业务数据发送至服务器,服务器程序将数据入库至MySQL数据库。服务器中的javaWEB程序将数据展示到网页上供用户查看。

原数据库设计

  • windows单机主从分离

  • 已分表分库,按年分库,按天分表

  • 每张表大概20w左右的数据

原查询效率

3天数据查询70-80s

目标

3-5s

业务缺陷

无法使用sql分页,只能用java做分页。

问题排查

前台慢 or 后台慢

  • 如果你配置了druid,可在druid页面中直接查看sql执行时间和uri请求时间

  • 在后台代码中用System.currentTimeMillis计算时间差。

结论 : 后台慢,且查询sql慢

sql有什么问题

  • sql拼接过长,达到了3000行,有的甚至到8000行,大多都是uNIOn all的操作,且有不必要的嵌套查询和查询了不必要的字段

  • 利用explain查看执行计划,where条件中除时间外只有一个字段用到了索引

备注 : 因优化完了,之前的sql实在找不到了,这里只能YY了。

查询优化

去除不必要的字段

效果没那么明显

去除不必要的嵌套查询

效果没那么明显

分解sql

  • 将union all的操作分解,例如(一个union all的sql也很长)

select aa from bb_2018_10_01 left join ... on .. left join .. on .. where .. union all select aa from bb_2018_10_02 left join ... on .. left join .. on .. where .. union all select aa from bb_2018_10_03 left join ... on .. left join .. on .. where .. union all select aa from bb_2018_10_04 left join ... on .. left join .. on .. where ..

将如上sql分解成若干个sql去执行,最终汇总数据,***快了20s左右。

select aa from bb_2018_10_01 left join ... on .. left join .. on .. where ..

将分解的sql异步执行

利用java异步编程的操作,将分解的sql异步执行并最终汇总数据。这里用到了CountDownLatch和ExecutorService,示例代码如下:

// 获取时间段所有天数        List<String> days = MyDateUtils.getDays(requestParams.getStartTime(), requestParams.getEndTime());        // 天数长度        int length = days.size();        // 初始化合并集合,并指定大小,防止数组越界        List<你想要的数据类型> list = Lists.newArrayListWithCapacity(length);        // 初始化线程池        ExecutorService pool = Executors.newFixedThreadPool(length);        // 初始化计数器        CountDownLatch latch = new CountDownLatch(length);        // 查询每天的时间并合并        for (String day : days) {            Map<String, Object> param = Maps.newHashMap();            // param 组装查询条件             pool.submit(new Runnable() {                @Override                public void run() {                    try {                        // mybatis查询sql                        // 将结果汇总                        list.addAll(查询结果);                    } catch (Exception e) {                        logger.error("getTime异常", e);                    } finally {                        latch.countDown();                    }                }            });        }          try {            // 等待所有查询结束            latch.await();        } catch (InterruptedException e) {            e.printStackTrace();        }         // list为汇总集合        // 如果有必要,可以组装下你想要的业务数据,计算什么的,如果没有就没了

结果又快了20-30s

优化MySQL配置

以下是我的配置示例。加了skip-name-resolve,快了4-5s。其他配置自行断定

 [client] port=3306 [mysql] no-beep default-character-set=utf8 [mysqld] server-id=2 relay-log-index=slave-relay-bin.index relay-log=slave-relay-bin  slave-skip-errors=all #跳过所有错误 skip-name-resolve  port=3306 datadir="D:/mysql-slave/data" character-set-server=utf8 default-storage-engine=INNODB sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"  log-output=FILE general-log=0 general_log_file="WINDOWS-8E8V2OD.log" slow-query-log=1 slow_query_log_file="WINDOWS-8E8V2OD-slow.log" long_query_time=10  # Binary Logging. # log-bin  # Error Logging. log-error="WINDOWS-8E8V2OD.err"   # 整个数据库***连接(用户)数 max_connections=1000 # 每个客户端连接***的错误允许数量 max_connect_errors=100 # 表描述符缓存大小,可减少文件打开/关闭次数 table_open_cache=2000 # 服务所能处理的请求包的***大小以及服务所能处理的***的请求大小(当与大的BLOB字段一起工作时相当必要)   # 每个连接独立的大小.大小动态增加 max_allowed_packet=64M # 在排序发生时由每个线程分配 sort_buffer_size=8M # 当全联合发生时,在每个线程中分配  join_buffer_size=8M # cache中保留多少线程用于重用 thread_cache_size=128 # 此允许应用程序给予线程系统一个提示在同一时间给予渴望被运行的线程的数量. thread_concurrency=64 # 查询缓存 query_cache_size=128M # 只有小于此设定值的结果才会被缓冲   # 此设置用来保护查询缓冲,防止一个极大的结果集将其他所有的查询结果都覆盖 query_cache_limit=2M # InnoDB使用一个缓冲池来保存索引和原始数据 # 这里你设置越大,你在存取表里面数据时所需要的磁盘I/O越少.   # 在一个独立使用的数据库服务器上,你可以设置这个变量到服务器物理内存大小的80%   # 不要设置过大,否则,由于物理内存的竞争可能导致操作系统的换页颠簸.   innodb_buffer_pool_size=1G # 用来同步IO操作的IO线程的数量 # 此值在Unix下被硬编码为4,但是在Windows磁盘I/O可能在一个大数值下表现的更好.  innodb_read_io_threads=16 innodb_write_io_threads=16 # 在InnoDb核心内的允许线程数量.   # ***值依赖于应用程序,硬件以及操作系统的调度方式.   # 过高的值可能导致线程的互斥颠簸. innodb_thread_concurrency=9  # 0代表日志只大约每秒写入日志文件并且日志文件刷新到磁盘.   # 1 ,InnoDB会在每次提交后刷新(fsync)事务日志到磁盘上 # 2代表日志写入日志文件在每次提交后,但是日志文件只有大约每秒才会刷新到磁盘上 innodb_flush_log_at_trx_commit=2 # 用来缓冲日志数据的缓冲区的大小.   innodb_log_buffer_size=16M # 在日志组中每个日志文件的大小.   innodb_log_file_size=48M # 在日志组中的文件总数.  innodb_log_files_in_group=3 # 在被回滚前,一个InnoDB的事务应该等待一个被批准多久.   # InnoDB在其拥有的锁表中自动检测事务死锁并且回滚事务.   # 如果你使用 LOCK TABLES 指令, 或者在同样事务中使用除了InnoDB以外的其他事务安全的存储引擎   # 那么一个死锁可能发生而InnoDB无法注意到.   # 这种情况下这个timeout值对于解决这种问题就非常有帮助.  innodb_lock_wait_timeout=30 # 开启定时 event_scheduler=ON

被批准多久. # InnoDB在其拥有的锁表中自动检测事务死锁并且回滚事务. # 如果你使用 LOCK  TABLES 指令, 或者在同样事务中使用除了InnoDB以外的其他事务安全的存储引擎 # 那么一个死锁可能发生而InnoDB无法注意到. #  这种情况下这个timeout值对于解决这种问题就非常有帮助. innodb_lock_wait_timeout=30#  开启定时event_scheduler=ON

根据业务,再加上筛选条件

快4-5s

将where条件中除时间条件外的字段建立联合索引

效果没那么明显

将where条件中索引条件使用inner join的方式去关联

针对这条,我自身觉得很诧异。原sql,b为索引

select aa from bb_2018_10_02 left join ... on .. left join .. on .. where b = 'xxx'

应该之前有union all,union all是一个一个的执行,***汇总的结果。修改为

select aa from bb_2018_10_02 left join ... on .. left join .. on .. inner join (     select 'xxx1' as b2     union all     select 'xxx2' as b2     union all     select 'xxx3' as b2     union all     select 'xxx3' as b2 ) t on b = t.b2

结果快了3-4s

性能瓶颈

根据以上操作,3天查询效率已经达到了8s左右,再也快不了了。查看mysql的cpu使用率和内存使用率都不高,到底为什么查这么慢了,3天最多才60w数据,关联的也都是一些字典表,不至于如此。继续根据网上提供的资料,一系列骚操作,基本没用,没辙。

环境对比

因分析过sql优化已经ok了,试想是不是磁盘读写问题。将优化过的程序,分别部署于不同的现场环境。一个有ssd,一个没有ssd。发现查询效率悬殊。用软件检测过发现ssd读写速度在700-800M/s,普通机械硬盘读写在70-80M/s。

优化结果及结论

  • 优化结果:达到预期。

  • 优化结论:sql优化不仅仅是对sql本身的优化,还取决于本身硬件条件,其他应用的影响,外加自身代码的优化。

到此,关于“MySQL中的SQL优化实战记录”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

您可能感兴趣的文档:

--结束END--

本文标题: MySQL中的SQL优化实战记录

本文链接: https://www.lsjlt.com/news/60932.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • MySQL中的SQL优化实战记录
    这篇文章主要介绍“MySQL中的SQL优化实战记录”,在日常操作中,相信很多人在MySQL中的SQL优化实战记录问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”MySQL中的S...
    99+
    2022-10-18
  • 记一次SQL优化的实战记录
    目录前言1. 创建表2. 需求3. 给表插入数据4. 开始根据需求写SQL4.1 第一版4.2 第二版4.3 第三版总结前言 昨天(2022-7-22)上线了我的一个功能,测试环境数据量较小,问题不大,但是上生产之后,直...
    99+
    2022-07-24
    sql优化最佳实践 SQL优化技巧 数据库SQL优化
  • MySQL千万级数据表的优化实战记录
    前言 这里先说明一下,网上很多人说阿里规定500w数据就要分库分表。实际上,这个500w并不是定义死的,而是与MySQL的配置以及机器的硬件有关。MySQL为了提升性能,会将表的索引...
    99+
    2022-11-12
  • 关于Swagger优化的实战记录
    目录背景探察&解决一、先看看v1加载慢,却要加载两次。二、接下来处理v1加载慢三、将需返回json数据四、修改Swagger页面结语背景 尽管.net6已经发布很久了,但是公...
    99+
    2022-11-13
  • Java优化if-else代码的实战记录
    目录前言 方案一: 数组 方案二:HashMap 由 key 获取 value 由 value 获取 key 解决方案三:枚举 总结 前言 开发系统一些状态,比如订单状态:数据库存...
    99+
    2022-11-12
  • MySQL--------SQL优化审核工具实战
    1. 背景   SQLAdvisor是由美团点评公司技术工程部DBA团队(北京)开发维护的一个分析SQL给出索引优化建议的工具。它基于MySQL原生态词法解析,结合分析SQL中的wher...
    99+
    2022-10-18
  • MySQL实战记录之如何快速定位慢SQL
    目录开启慢查询日志系统变量修改配置文件设置全局变量分析慢查询日志mysqldumpslowpt-query-digest用法实战总结开启慢查询日志 在项目中我们会经常遇到慢查询,当我...
    99+
    2022-11-13
  • (9)MySQL进阶篇SQL优化(InnoDB锁-记录锁)
    1.概述 InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不同,后者是通过在数据块中对相应数据行加锁来实现的。InnoDB这种行锁实现特点意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,否则I...
    99+
    2019-08-22
    (9)MySQL进阶篇SQL优化(InnoDB锁-记录锁)
  • vue项目打包优化的方法实战记录
    目录1.按需加载第三方库2.移除console.log3. Close SourceMap4. Externals && CDN5.路由懒加载的方式总结1.按需加载第...
    99+
    2022-11-13
  • 记录MySQL中优化sql语句查询常用的30种方法
    对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。2.应尽量避免在 where 子句中使用!=或操作符,否则将引擎放弃使用索引而进行全表扫描。3.应尽量避免...
    99+
    2014-05-10
    记录MySQL中优化sql语句查询常用的30种方法
  • Mysql查询最近一条记录的sql语句(优化篇)
    下策——查询出结果后将时间排序后取第一条 select * from a where create_time<="2017-03-29 19:30:36" order by...
    99+
    2022-10-18
  • MySQL 5.6主从报错的实战记录
    1. 问题现象 版本:MySQL 5.6,采用传统 binlog file & pos 方式配置的主从复制结构。 实例重启后,主从复制报错如上图所示。 2. 错误含义 错误分为2部分。 第一部分 ...
    99+
    2022-05-26
    mysql5.6主从配置 mysql5.6主从报错 mysql 主从配置
  • oracle性能优化(项目中的一个sql优化的简单记录)
    在项目中,写的sql主要以查询为主,但是数据量一大,就会突出sql性能优化的重要性。其实在数据量2000W以内,可以考虑索引,但超过2000W了,就要考虑分库分表这些了。本文主要记录在实际项目中,一个需要查询很慢的sql的优化过程,如果有更...
    99+
    2015-11-21
    oracle性能优化(项目中的一个sql优化的简单记录)
  • 一次docker登录mysql报错问题的实战记录
    目录起因解决方法附:docker下进入mysql命令行总结起因 最近想再重温重温MySQL,于是就打开VMware登上了我的小破机。想着之前在docker上面已经装过MySQL了,就...
    99+
    2022-11-13
  • 一次SQL如何查重及去重的实战记录
    目录前言⛳️1.distinct⛳️2.groupby⛳️3.row_number窗口函数⛳️4.删除重复数据第一步:找出重复的数据第二步:删除重复的数据总结前言 在使用SQL提数的...
    99+
    2022-11-13
  • 一次数据库查询超时优化问题的实战记录
    目录问题发现查找原因解决问题额外话:Transaction Timeout、Statement Timeout、Socket timeout 的区别它们三者的关系是在怎样的呢总结参数...
    99+
    2022-11-12
  • MySQL深分页问题解决的实战记录
    目录前言limit深分页为什么会变慢?通过子查询优化回顾B+ 树结构把条件转移到主键索引树INNER JOIN 延迟关联标签记录法使用between...and...手把手实战案例一...
    99+
    2022-11-12
  • mysql中怎么优化插入记录速度
    mysql中怎么优化插入记录速度,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。一. 对于MyISAM引擎表常见的优化方法如下:1. 禁用索引。...
    99+
    2022-10-18
  • 一次现场mysql重复记录数据的排查处理实战记录
    目录前言 分析 数据总计 重复次数占比 where 和 having 的区别 总结 前言 我当时正好出差在客户现场部署调试软件,有一天客户突然找到我这里,说他们...
    99+
    2022-11-12
  • vue引入iconfont图标库的优雅实战记录
    目录前言 生成SVG svg sprites简介 获取项目图标 项目设置 图标引用 组件引用 多主题支持 配置多主题样式 Icon改造 页面校验 尾言 前言 本文撰写的初衷是为了向...
    99+
    2022-11-12
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作