Code前端首页关于Code前端联系我们

MYSQL 5.7

terry 2年前 (2023-09-26) 阅读数 48 #后端开发

性能优化体验该业务主要是为商家提供 B2B 服务。我们大约有 750 名交易员,但活跃的交易员并不多。业务订单表为每周20万个订单。购买阿里云RDS FOR MYSQL 5.7 8核16GB专属服务。

计划申请基本分为运营结束、销售结束、商户结束、交易结束。基本上是 4 个微服务!另外还有微服务的监控和运行。

我设计了一个慢SQL基线,虽然1秒的标准RDS是慢SQL并且保存的。当然,不需要优化1秒。有的伙伴规定5秒。我这里规定最后一次操作是10秒,销售和交易员最后5秒,最后一笔交易是1秒。 。主要是由于要检查的数据量和用户身份的差异而进行规划。毕竟,运营商经常会检查所有商户的多个订单数据。当然,商家也会查看自己过去某个月份的数据,但他们是我们的客户,他们的身份是有价值的!他们应该被认真对待。使用缓慢会给您带来不好的体验,应该在抱怨之前进行优化。另外,往往顾客会选择用脚。

经验关联表1

select count(*)from order aleft join b on a.merchant_no=b.merchant_noleft join c on a.channel_code=c.channel_codeleft join d on a.product_code = d.channel_codewhere 1=1and b.subname='?'and a.create_time >='?' and a.create_time <='?'and a.pay_time >='?' and a.pay_time <='?'and a.merchant_no='?';

基本SQL是这样的 上面是分页统计的总数。还有SQL分页。为了快速交付,JAVA开发者喜欢使用分页插件。分页插件只是将子查询层包装在 SQL 分页之外。其实上面有一个表是不需要参与关联的,也不妨碍最终得到的Total。

MYSQL 5.7 性能优化心得篇

从图形执行计划来看,主表与三个表关联的行数为 5.69K。理论上数据会更少。 RDS的计算方式是乘法!就是A* B*C*D=5.69K*1*1*1 这是索引。5.69K(千行)^3

以前的ORACLE算法是乘法+加法。

(((A *B)* C) *D)=5.69K*1
=569*1
=569*1

=5.69K+569+569

因此,请重点关注此优化,而不是关系,如果你可以。通过JAVA MAP的IF判断

select count(*)from order aleft join b on a.merchant_no=b.merchant_no<if parameter not null > <left join c on a.channel_code=c.channel_code >left join d on a.product_code = d.channel_codewhere 1=1and b.subname='?'and a.create_time >='?' and a.create_time <='?'and a.pay_time >='?' and a.pay_time <='?'and a.merchant_no='?';

的原理是什么?可能我猜测是MYSQL把服务层和引擎层分开了
过滤条件在服务层处理,而索引条件下推到引擎层处理。

那么关联必须在引擎层进行,

即先在引擎中进行如下关联

from order aleft join b on a.merchant_no=b.merchant_noleft join c on a.channel_code=c.channel_codeleft join d on a.product_code = d.channel_code

,然后在服务层进行过滤

where 1=1and b.subname='?'and a.create_time >='?' and a.create_time <='?'and a.pay_time >='?' and a.pay_time <='?'and a.merchant_no='?';

这就可以解释为什么MYSQL LEFT JOIN其实是INNER JOIN

驾驶体验小表
在ORACLE的经验中,小表带动天津最好的大表!狗不理包子。 MYSQL也出现这种情况其实小表带动大表比较慢

select a.*from order aleft join b on a.merchant_no=b.merchant_noleft join c on a.channel_code=c.channel_code left join d on a.product_code = d.channel_codewhere 1=1and b.subname='?'and a.create_time >='?' and a.create_time <='?'and a.pay_time >='?' and a.pay_time <='?'and a.merchant_no='?';

执行计划可能是B JOIN A,JOIN C,JOIN D
因为按照经典理论,B产生的量很少,所以应该可以用作驾驶台。事实上,它最终会导致更长的执行时间。为什么?你只需要看看源代码就可以理解一些东西!也许你花了精力看源代码,结果发现它很小,但结果发现它是在MYSQL8.0中优化的。至于是否有优化,我还没有确认!主要公司业务运行在5.7上。另外两个项目运行在 8.0.25 上。它们数量不多,而且看不见。

为了避免这种情况,我们使用非标准的 STRAIGHT_JOIN 链接。这和你的写作顺序有关。 .

select a.*from order aSTRAIGHT_JOIN b on a.merchant_no=b.merchant_noSTRAIGHT_JOIN c on a.channel_code=c.channel_code STRAIGHT_JOIN d on a.product_code = d.channel_codewhere 1=1and b.subname='?'and a.create_time >='?' and a.create_time <='?'and a.pay_time >='?' and a.pay_time <='?'and a.merchant_no='?';

经验3 ORDER BY

select a.*from order aSTRAIGHT_JOIN b on a.merchant_no=b.merchant_noSTRAIGHT_JOIN c on a.channel_code=c.channel_code STRAIGHT_JOIN d on a.product_code = d.channel_codewhere 1=1and b.subname='?'and a.create_time >='?' and a.create_time <='?'and a.pay_time >='?' and a.pay_time <='?'and a.merchant_no='?'order by create_time desc limit 0,10;

5.7 优化器在这里可以使用CREAT_TIME索引,因为感觉通过索引可以避免FILE SORT排序操作,而且因为LIMIT返回的数字很小。
甚至OPTIMER提到过。 TRACE显示CREAT_TIME索引代价昂贵,最优索引是PAY_TIME。它实际上运行需要6秒,因为符号条件的数据量很小,所以如果你想找到所有内容,你必须扫描整个CREATE_TIME索引。即CREATE_TIME索引被推送到引擎,每次引擎产生数据时,服务层NO并继续帮助扫描。事实上,优化器并没有考虑CBO成本。

如何优化?也许MYSQL 8.0直方图可以解决这个排序问题。

如果删除了索引,感觉不太对劲,可能会影响其他SQL。

第4课看看值的范围

值的范围是多少?就是时间条件再次变成某个值之后,就会自动改变执行计划。原来通过索引的东西现在是别的东西了!

select a.*from order aSTRAIGHT_JOIN b on a.merchant_no=b.merchant_noSTRAIGHT_JOIN c on a.channel_code=c.channel_code STRAIGHT_JOIN d on a.product_code = d.channel_codewhere 1=1and b.subname='微信'and a.create_time >='2022-01-01' and a.create_time <='2022-01-31'and a.pay_time >='2022-01-01' and a.pay_time <='2022-01-02'and a.merchant_no='009'order by create_time desc limit 0,10;

and a.pay_time

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门