暂无图片
MySQL SQL优化,干预表关联顺序
我来答
分享
徐孝亮
2024-06-13
MySQL SQL优化,干预表关联顺序

MySQL 5.7

大家看下这个SQL语句,目前a和b两张表,执行计划中a是驱动表,b是被驱动表。

请问能否干预两张表的关联顺序,让b成为驱动表,a做驱动表。

MySQL8.0有相关的hint,但是5.7只能用straight_join。但是用b straight_join a的话,就变成了更新b表了,语义就变了。

感觉这是MySQL的一个缺陷,大家看有没有好的办法干预两表执行计划的关联顺序

update a
inner join b on a.sub_bill_id = b.sub_bill_id
left join c on a.bill_id = c.bill_id
and c.`is_deleted` = 0
set
a.`card_bill_id` = b.card_bill_id,
a.card_sub_bill_id = b.card_sub_bill_id
WHERE
c.id IS NULL
AND a.is_deleted = '0'
AND b.`biz_bill_day` >= '2024-06-01';

我来答
添加附件
收藏
分享
问题补充
3条回答
默认
最新
徐孝亮
升级问题到: 潜在风险
暂无图片 评论
暂无图片 有用 1
打赏 0
风行

升级问题到: 潜在风险

暂无图片 评论
暂无图片 有用 0
打赏 0
龙镇君

在 MySQL 5.7 中,确实无法像 MySQL 8.0 那样使用显式的 JOIN hint 来指定表的连接顺序。然而,可以通过优化查询语句的写法来尽量影响 MySQL 查询优化器的执行计划。

在你的情况下,a 表作为驱动表,b 表作为被驱动表,但你希望反过来。一种可行的方法是通过重构查询语句,强制 MySQL 使用你期望的连接顺序。以下是一种可能的重构方式:

update b
inner join a on a.sub_bill_id = b.sub_bill_id
left join c on a.bill_id = c.bill_id and c.is_deleted = 0
set
b.card_bill_id = a.card_bill_id,
b.card_sub_bill_id = a.card_sub_bill_id
where
c.id is null
and a.is_deleted = '0'
and b.biz_bill_day >= '2024-06-01';
复制

在这个重构后的语句中,我们将 update 操作的主要对象从 a 改为 b,并将 a 表放在 join 子句中的后面。这样一来,MySQL 在优化查询时,可能会将 b 表视为驱动表,a 表作为被驱动表。

请注意,这种方法并不是百分之百保证 MySQL 就会按照你的期望进行优化,因为 MySQL 查询优化器的行为取决于多个因素,包括索引统计信息、数据分布等。但是,这种重构通常可以影响执行计划的选择,使你的期望结果更有可能实现。

另外,确保在 b 表上的字段上存在索引,尤其是 sub_bill_id 字段,可以帮助 MySQL 在执行计划中更有效地选择驱动表。

总结来说,虽然 MySQL 5.7 中无法像 MySQL 8.0 那样直接使用 JOIN hint 来指定连接顺序,但通过巧妙地重构查询语句和优化表结构,你可以在很大程度上影响 MySQL 的查询优化器,使其更倾向于按照你期望的方式执行连接。

暂无图片 评论
暂无图片 有用 0
打赏 0
徐孝亮
题主
2024-07-08
请注意:这个语句原来是把b的值赋给a:set a.`card_bill_id` = b.card_bill_id, a.card_sub_bill_id = b.card_sub_bill_id 请问下:这么改写是不是把a的值赋给b了?意思变了吧?
回答交流
Markdown


请输入正文
提交
问题信息
请登录之后查看
邀请回答
暂无人订阅该标签,敬请期待~~
暂无图片墨值悬赏