首页 > 解决方案 > 为什么 MySQL 会更改不同数据库中查询的联接类型

问题描述

我们有不同的 RDS(AWS、GCP 等),这些 RDS 有很多数据库。我们的每个数据库都由相同的后端代码构建和管理,因此所有表和数据集都匹配。

我有一个查询,当我专门在一个数据库上运行时,它会停止运行,并且比较解释表明它正在被不同地对待。

所以对于这个例子,我有 first_table,这个 FK 是 second_table。所有索引等都正确形成。现在假设我们的 AWS RDS 上有 db_one,我们的 GCP 数据库服务器上有 db_two 和 db_three。

db_one 上的 first_table 为 2gb,db_two 为 8.8gb,db_three 为 20mb。我们要对其进行 FK 处理的 second_table 只有 64kb。

select * from first_table a
where first_table a.my_date between '2020-12-01 00:00:00' and '2020-12-01 00:00:00';

如果我在每个数据库上运行它,查询需要不到一秒钟的时间来运行和返回。在 db_two 上,由于大小的原因,通过网络将数据传输给我需要几秒钟的额外时间 - 这很好,也是意料之中的。

当我运行explain它时,它显示“类型:范围,表:a”。这在所有数据库中都是一致的。

现在,当我添加 FK 连接并在 db_one 上运行时。就像瞬间一样。

select * from first_table a
join second_table b on b.ft_id = a.id
where first_table a.my_date between '2020-12-01 00:00:00' and '2020-12-01 00:00:00';

但是,当我在 db_two (最大的)上运行它时,它永远不会完成。
现在,当我在两个数据库上运行解释时,它们是不同的。

在 db_one 上,它仍然使用“类型:范围,表:a”和“类型:eq_ref,表:b”

现在在 db_two 上显示:“表:b,类型:ALL,表:a,类型:ref”

所以我认为这些 RDS 之间可能存在差异,或者其他什么,所以我在 db_three(与 db_two 位于同一台服务器上)上运行查询和解释,它立即运行并且解释与 db_one 上的相同。
事实上,我在不同数据库上对我们所有的 RDS 进行了解释,这始终是我所期望的:“表:a,类型:范围。表:b,类型:eq_ref”。

只有在具有最大表的 db_two 上,解释有所不同,但性能也很差。

谁能帮助解释为什么会这样?或者是什么原因造成的,我可以解决它吗?

我目前的解决方法就是跑快单表sql,然后返回python,然后拉取FK数据,自己手动拼接排序。至少那会运行。
但这似乎很疯狂。

希望我想念这里的一些东西。

标签: mysql

解决方案


推荐阅读