PHP数组差异与MySQL NOT IN的比较

4

我将尝试比较两个表中的两列邮政编码,以查看第二个表中是否缺少值。

我最初想使用mysql进行操作,我的查询大致如下:

'SELECT code FROM t1 WHERE t1 NOT IN (select code FROM t2)'

但是它真的很慢,所以我尝试了另一种方法: 我做了两个选择,然后用array_diff()比较结果。

使用mysql:几分钟,有时会崩溃

使用PHP:少于1秒。

有人能解释这些差异吗? 我的SQL查询有问题吗?


5
可以使用 LEFTRIGHT JOIN 轻松地检查一张表中缺失的值(与另一张表相比),这就是它们所用的操作方式。或者可以查看这个链接:https://dev59.com/HkrSa4cB1Zd3GeqPVU8B - serjoscha
两个表格大约有 50,000 行。 @serjoscha:这是一个好主意。我使用的示例在多个 SO 线程中都可以找到,所以它看起来很好。 - FLX
2
好的,那么你的问题解决了吗?---------还有一件事:array_diff不是一个好主意,因为:要使用array_diff,需要从SQL服务器中获取整个数据,然后才能确定差异。这不是性能编程的好方法。但是,当使用mysql解决您的问题时,所有操作都在服务器上进行,只有结果会被发送回给您。在几乎所有情况下,这是实现脚本的更快更快更快的方式。 - serjoscha
2
@FC - 如果您没有索引,那么一定要添加一个,因为这将加快查询速度。您可以像这样添加索引:ALTER TABLE <table> ADD INDEX code_idx (code) 这应该对两个表都进行。如果您执行 EXPLAIN 查询,您会看到类似于 Using where; Using index; Using join buffer 的内容,这是好的 - Cyclonecode
@serjoscha:我应该说这是一次性查询,只是为了填补缺失的数据。这不是一个会定期运行的脚本。 - FLX
显示剩余4条评论
1个回答

3
如果您的主表有50k行,则在查询中使用子查询将导致1 + 50k次执行选择。一次是为了第一个表,另外50k次是每行一个选择。服务器会比较带子查询的行,而这个子查询在迭代主表时每次都会重新加载。这就是为什么您的SQL代码需要时间,并且也可能是巨大的内存问题。
请参见serjoschas关于联接的信息,以便在SQL中修复它,这应该比您的PHP解决方案更快。

检查表中缺失哪些值(与另一个表相比)可以轻松地通过左或右连接来完成,它们只是为此类操作而制作的...或者看看这篇文章:如何在两个MySQL表之间查找缺失值- serjoscha

一个解决方案:
SELECT code FROM t1
WHERE code NOT IN ( SELECT code FROM t2 )

将会是:

SELECT t1.code 
FROM t1
LEFT JOIN t2
ON t1.code = t2.code
WHERE t2.code is null

试一下。 此外,如 Cyclone 所建议的那样,请查看索引

如果您没有索引,则应该添加一个,因为这将加快查询速度。您可以像这样添加索引:ALTER TABLE ADD INDEX code_idx(code),这应该针对两个表进行操作。如果您执行查询的 EXPLAIN,您将看到类似于 Using where; Using index; Using join buffer 的内容,这是很好的 - Cyclone

索引可以加快查询速度。 如果表只提供一个列,则使用与源表相同内容的索引表搜索将完全相同且冗余。否则,我强烈建议在t2的代码列上创建索引,这会大大提高性能并减少内存消耗。


1
他还需要在所选字段中使用表名,例如 SELECT t1.code,因为在这种情况下 code 是不明确的。 - Cyclonecode
谢谢,我已经修复了那个问题和索引部分。 - Daniel
1
谢谢,总结得很好。也感谢Cyclone和serjoscha。 - FLX

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接