2009-06-15 62 views
1

因此,假设我正在构建该联系人管理系统。有一个USER表和一个CONTACT_INFO表。 对于每个USER,我可以有零个或多个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记录时不应该成本高昂,性能明智。

一如既往,赞赏反馈。

+1

您应该尝试下面的几个选项,然后确定每个选项的查询计划和性能,并选择最好的一个。 – 2009-06-16 16:51:26

+0

我们在谈论哪些DBMS? – AakashM 2009-06-16 16:55:07

回答

2

从我的测试,以下是比BradC的方法更快:

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

这可能是因为编译器要做的转换本身,我不知道。尽管如此:如果你已经在数据库中设置了索引(即两个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 

第二方案可能不在你的情况下很有用,但我发现它比我假设的一些更简单的查询会自动优化更快。

3

最简单方法是:

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

它看起来更臃肿,但应更好地扩展。

+0

我测试过的优化器把这个同样地看作是一个简单的NOT EXISTS。(但是对于很多情况来说,这是一个很棒的技术,而且稍微更便携,这意味着它可以在老版本的MySQL中工作。) – dkretz 2009-06-15 22:42:41

1

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

1

至少在Oracle中,我获得使用

其中0 =(SELECT COUNT(*)从CONTACT_INFO C,其中...)

代替NOT IN子句中更好的性能。

相关问题