mysql - 两个表之间的 "Join"非常快,而 "Left join"则非常慢(MySQL DB)

标签 mysql sql performance

我有两个表(每个表大约 300,000 行),其中一个列标识符列 (ID) 已建立索引。以下查询需要几秒钟:

SELECT *
FROM Table_1 a JOIN Table_2 b on a.ID=b.ID

与以下需要数小时的查询相比:

SELECT *
FROM Table_1 a LEFT JOIN Table_2 b on a.ID=b.ID

这两个查询之间的区别在于,一个是使用“连接”完成的,另一个是使用“左连接”完成的。

查询结果需要包含Table_1中的所有行,所以我别无选择,只能执行“左连接”。

也尝试了这种方法,但也花费了很多时间:

SELECT *
FROM Table_1 a JOIN Table_2 b on a.ID=b.ID

UNION

SELECT *
FROM Table_1 a LEFT JOIN Table_2 b on a.ID=b.ID
WHERE b.ID is null;

有什么建议吗?

谢谢提前分配...

最佳答案

根据提供的信息,我只能想到尝试这样的事情:

SELECT a.*, b.column1, b.column2, ..., column(n)
FROM Table_1 a JOIN Table_2 b on a.ID=b.ID

UNION

SELECT a.*, '' AS column1, '' AS column2, ..., '' as column(n)
FROM Table_1 a 
WHERE a.ID NOT IN 
    (SELECT a.ID FROM Table_1 a JOIN Table_2 b on a.ID=b.ID);

编辑:我想澄清为什么这更快,并使其成为更完整的答案。

这是因为服务器所遵循的计划达到了预期的结果。 左外连接例如:

SELECT *
FROM Table_1 a LEFT JOIN Table_2 b on a.ID=b.ID

它必须遍历 Table_1 中的每条记录,无论它是否与 Table_2 中的某些内容匹配。而且,随着 table 的增长,这变得越来越昂贵。

通过添加WHERE b.ID is null,它基本上必须通过非索引列来过滤先前操作的结果。而且,它必须首先创建这些空值才能执行此操作,因此它可能不会创建更优化的计划。

SELECT a.ID 
FROM Table_1 a 
JOIN Table_2 b on a.ID=b.ID

内连接利用了更好的算法。而且,我们正在使用不在列表中的索引值。当表大小增加并且需要更多操作时,与对应的表相比,此方法的性能更好。但是,稍后我们可能会收到一些性能影响,因为内部联接返回大量索引来进行过滤。

self 以来,没有提供进一步的上下文,或更清晰的用例。我认为解决方案就足够了。但是,如果更好地理解整个问题,它可以得到改进。

关于mysql - 两个表之间的 "Join"非常快,而 "Left join"则非常慢(MySQL DB),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35020360/

相关文章:

sql - 交叉应用(选择顶部 1)比 row_number() 慢得多

php - 如何在 Magento 数据库中存储日期时间值?

mysql - 如何在 mySQL 查询中使用模糊分组

sql - 尝试在 Oracle SQL 上新创建的用户上创建序列时,出现 "user or role ' ' 不存在”

java - Java.sql 的 getRow() 线程安全吗?

performance - Matlab + CUDA 求解矩阵向量方程 A*x=B 速度慢

php - 如何获得id的降序

php - 使用 php mysql 显示外键值

php - SQL 命令在 Laravel 5.7 中未给出预期结果。我需要修改我的表或查询吗?

delphi - 有没有办法保存对象的状态以便以后更快地重新加载?