我有两个表(每个表大约 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/