如何加快这个简单的查询?

时间:2011-11-15 20:38:03

标签: sql sql-server-2008 tsql where-clause

想象一下,你有这3张桌子:

enter image description here

根据这种模式,可以想象有大量的数据。

当我运行这样的查询时:

SELECT DISTINCT tPerson.Name, tPerson.Town
FROM tPerson
JOIN tPersonTypeCodeMap ON tPersonTypeCodeMap.PersonId = tPerson.Id
JOIN tPersonHobbyCodeMap ON tPersonHobbyCodeMap.PersonId = tPerson.Id
WHERE tPersonTypeCodeMap.TypeCode IN ('C', 'S', 'P')

它运作得非常快!

但是当我添加第二个条件(NOT IN)时,查询需要很长时间:

SELECT DISTINCT tPerson.Name, tPerson.Town
FROM tPerson
JOIN tPersonTypeCodeMap ON tPersonTypeCodeMap.PersonId = tPerson.Id
JOIN tPersonHobbyCodeMap ON tPersonHobbyCodeMap.PersonId = tPerson.Id
WHERE tPersonTypeCodeMap.TypeCode IN ('C', 'S', 'P')
 OR tPersonHobbCodeMap.HobbyCode NOT IN ('SKATE','CLIMBING') 

您能否告诉我减慢查询的原因是什么?如何让它更快地运作?

2 个答案:

答案 0 :(得分:2)

在第一个查询中,大多数过滤可以通过仅查看单个表(tpersonTypeCodeMap)来完成。在第二个示例中,需要连接两个表来执行过滤。此外,一旦引入“OR”,就会失去任何索引的效果。

你真的希望“OR”在这两个过滤器上运行,而不是“AND”吗?此外,您是否希望每个人返回多条记录,具体取决于它们匹配的TypeCode数量以及它们失败匹配的HobbyCodes数量?

如果条件“OR”实际上是你想要的,你可以使用:

SELECT tPerson.Name, tPerson.Town
FROM tPerson JOIN tPersonTypeCodeMap 
     ON tPersonTypeCodeMap.PersonId = tPerson.Id
WHERE tPersonTypeCodeMap.TypeCode IN ('C', 'S', 'P')
UNION
SELECT tPerson.Name, tPerson.Town JOIN tPersonHobbyCodeMap 
       ON tPersonHobbyCodeMap.PersonId = tPerson.Id
WHERE tPersonHobbCodeMap.HobbyCode NOT IN ('SKATE','CLIMBING')

这将独立获取两组记录,然后将它们组合在一起。通过使用UNION而不是UNION ALL,将返回DISTINCT操作以将数据库减少为唯一行。

答案 1 :(得分:0)

NOT IN部分表现不佳。试试这个版本。

SELECT tPerson.Name, tPerson.Town
FROM tPerson
JOIN tPersonTypeCodeMap ON tPersonTypeCodeMap.PersonId = tPerson.Id
WHERE tPersonTypeCodeMap.TypeCode IN ('C', 'S', 'P')
 OR NOT EXISTS(SELECT NULL
                   FROM tPersonHobbCodeMap 
                   WHERE tPersonHobbCodeMap.PersonId = tPerson.id
                       AND tPersonHobbCodeMap.HobbyCode IN ('SKATE','CLIMBING') )