如何使用子查询优化“WHERE NOT IN”
Posted
技术标签:
【中文标题】如何使用子查询优化“WHERE NOT IN”【英文标题】:How to optimize "WHERE NOT IN" with subquery 【发布时间】:2014-01-14 10:19:09 【问题描述】:我有这个问题,这个线程中的讨论输出是什么:mysql JOIN subquery
查看当前小提琴:http://sqlfiddle.com/#!2/e97cf/22
create table c_contact
(id INT,
name VARCHAR(20),
securityid INT
);
create table c_monitoring
(started DATE,
ended DATE DEFAULT NULL,
securityid INT
);
SELECT
c_contact.id,
c_contact.name,
c_contact.securityid
FROM c_contact
WHERE c_contact.securityid != ''
AND c_contact.securityid NOT IN
(select securityid
from c_monitoring
where ended is null
group by securityid
)
GROUP BY c_contact.id ;
我到底要如何优化这个查询?我在 c_contact 表中有 100.000 条记录,在 c_monitoring 表中有大约 10.000 条记录。 127 个结果行的查询耗时 > 30 秒。
编辑:通过正确索引表解决了案例。
【问题讨论】:
如果您解决了问题,请添加解决方案(使用的索引)作为答案。 【参考方案1】:您的查询有一些 group by 问题(实际上,您不应该有任何 group by 子句),您应该将其转换为连接:
SELECT
c.id,
c.name,
c.securityid
FROM c_contact c
LEFT JOIN c_monitoring m ON m.securityid = c.securityid
AND m.ended is null
WHERE c.securityid != ''
AND m.securityid IS NULL
见SQLFiddle
我还用别名稍微整理了查询。
【讨论】:
@AngularAddict 嗯?我有2行。你确定你刷新了页面?这是小提琴链接:sqlfiddle.com/#!2/e97cf/34 问我缓存了页面。作品。谢谢你。【参考方案2】:通过索引表字段解决了案例
c_contact.securityid c_monitoring.started c_monitoring.ended c_monitoring.securityid查询现在大约需要 200 毫秒
【讨论】:
以上是关于如何使用子查询优化“WHERE NOT IN”的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Laravel 中使用查询构建器来做到这一点? (子查询 WHERE NOT IN)
努力优化 Rails WHERE NOT IN 在 Rails 中的查询
Laravel Eloquent 在子查询中有两个“WHERE NOT IN”