MYSQL 5.7
性能优化体验该业务主要是为商家提供 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 a
left join b on a.merchant_no=b.merchant_no
left join c on a.channel_code=c.channel_code
left join d on a.product_code = d.channel_code
where 1=1
and 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。
从图形执行计划来看,主表与三个表关联的行数为 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 a
left 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_code
where 1=1
and 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 a
left join b on a.merchant_no=b.merchant_no
left join c on a.channel_code=c.channel_code
left join d on a.product_code = d.channel_code
,然后在服务层进行过滤
where 1=1
and 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 a
left join b on a.merchant_no=b.merchant_no
left join c on a.channel_code=c.channel_code
left join d on a.product_code = d.channel_code
where 1=1
and 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 a
STRAIGHT_JOIN b on a.merchant_no=b.merchant_no
STRAIGHT_JOIN c on a.channel_code=c.channel_code
STRAIGHT_JOIN d on a.product_code = d.channel_code
where 1=1
and 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 a
STRAIGHT_JOIN b on a.merchant_no=b.merchant_no
STRAIGHT_JOIN c on a.channel_code=c.channel_code
STRAIGHT_JOIN d on a.product_code = d.channel_code
where 1=1
and 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 a
STRAIGHT_JOIN b on a.merchant_no=b.merchant_no
STRAIGHT_JOIN c on a.channel_code=c.channel_code
STRAIGHT_JOIN d on a.product_code = d.channel_code
where 1=1
and 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前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。