想象一下,你有这3张桌子:
根据这种模式,可以想象有大量的数据。
当我运行这样的查询时:
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')
您能否告诉我减慢查询的原因是什么?如何让它更快地运作?
答案 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') )