1

所以假设我正在构建这个联系人管理系统。有一个 USER 表和一个 CONTACT_INFO 表。对于每个用户,我可以有零个或多个 CONTACT_INFO 记录。按照我定义的方式,我在我的 CONTACT_INFO 表中设置了一个外键来指向相关的 USER 记录。

我想搜索所有没有 CONTACT_INFO 记录的 USER 记录。

我希望这可以做到:

SELECT * FROM user u WHERE u.user_id NOT IN (SELECT DISTINCT c.user_id FROM CONTACT_INFO);

我担心的是随着表的增长,这个查询的性能会显着下降。

我正在玩的一个想法是在 USER 表中添加一列,说明它是否有任何 CONTACT_INFO 记录。另外,我想知道,如果在将任何记录插入 CONTACT_INFO 时,DBMS 必须验证该记录是否存在,它已经在访问该记录以进行验证,因此在我更新 CONTACT_INFO 记录时更新它不应该是昂贵的,性能方面的。

与往常一样,我们感谢您的反馈。

4

4 回答 4

3

最简单的方法是:

SELECT (...) 
FROM user u
LEFT OUTER JOIN CONTACT_INFO c
ON u.user_id = c.user_id
WHERE c.user_id IS NULL

它看起来更笨重,但应该可以更好地扩展。

于 2009-06-15T22:39:17.010 回答
2

根据我的测试,以下方法比 BradC 的方法更快:

select (...)
from user u
where not exists (select null from CONTACT_INFO c where u.user_id = c.user_id)

这可能是因为编译器确实必须自己进行转换,我不知道。

不过,Le Dorfier 原则上是正确的:如果您已经在数据库上设置了索引(即两个 user_id 列都应该被索引),那么无论您有多少记录,您的答案和这里的大多数响应都将非常快在你的数据库中有。

顺便说一句,如果您正在寻找一种方法来获取列出用户以及“HasContactInfo”布尔值的查询,您可以执行以下操作:

select u.(...), 
  (case when exists (select null from CONTACT_INFO c where c.user_id = u.user_id) then 1
        else null
        end) has_contact_info
from user u

第二个解决方案在您的情况下可能没有用,但我发现它比我认为会自动优化的一些更简单的查询要快得多。

于 2009-06-15T23:00:34.337 回答
1

您有任何理由认为性能会下降吗?这是 SQL 中最有效的查询类型之一。但放弃 DISTINCT。

于 2009-06-15T22:39:58.273 回答
1

至少在 oracle 中,我使用获得了更好的性能

where 0 = (select count(*) from CONTACT_INFO c where...)

而不是 NOT IN 子句。

于 2009-06-15T23:47:35.067 回答