我有两个表,每个表包含大约500个客户数据记录。每个表中的每条记录都有一个电子邮件字段。有时两个表上都存在相同的电子邮件地址,有时则不存在。我想检索table1上table2上不存在的每个电子邮件地址。每个表中的电子邮件字段都已编制索引。我正在使用一个非常慢的子查询进行选择,10到20秒。
select email
from
t1
where
email not in (select email from t2)
每张桌子实际上有大约30K行,但是我可以很快将其击倒到500,并且按类别过滤“where”。只有当我添加子查询时它才会显着减速。所以,我确信这可以更快,我知道连接应该比子查询快得多,但无法弄清楚如何做到这一点。我在SO上找到了一个左外连接解释,看起来应该有所帮助,但无处可去。任何帮助表示赞赏。
答案 0 :(得分:4)
mysql不优化WHERE子句中的子查询(编辑:它为每个测试的行重新运行子查询)
转换为JOIN,尝试类似
的内容SELECT email FROM t1
LEFT JOIN t2 ON (t1.email = t2.email)
WHERE t2.email IS NULL
这应该运行得非常快,一个覆盖索引查询。 查询优化器应该走t1的电子邮件索引,检查 电子邮件索引为t2,并输出那些在t1但不在t2中的电子邮件。
编辑:我应该添加,mysql 优化JOIN子句中的子查询:它运行子查询并将结果放入“派生表”(没有任何索引的临时表)和连接派生表和其他任何表一样。语法有点滑稽,每个派生表必须有一个别名,即... JOIN (SELECT ...) AS derived ON ...
。
答案 1 :(得分:2)
通常,子查询比常规查询执行更多处理。在您的情况下,它首先从t2获取所有电子邮件,并将其与t1的电子邮件列表进行比较。
您可以尝试如下,而不使用子查询。
SELECT email FROM t1,t2 WHERE t1.email!=t2.email
答案 2 :(得分:1)
提高SELECT
操作性能的最佳方法是在查询中测试的一个或多个列上创建索引。索引条目的作用类似于表行的指针,允许查询快速确定哪些行与WHERE
子句中的条件匹配,并检索这些行的其他列值。可以索引所有MySQL数据类型。
创建mysql表的一些技巧.. see this.
答案 3 :(得分:0)
我认为这应该可以正常使用
SELECT email from T1
LEFT JOIN T2
ON T1.email=T2.email
WHERE T2.email!=NULL