SQL Server T-SQL查询优化

时间:2014-09-10 14:49:52

标签: sql sql-server performance optimization query-optimization

我正在尝试优化以下T-SQL查询:

SELECT Person.*
FROM Person
WHERE ZipCode LIKE '123%'
AND City = 'Washington'
AND NumberOfHomes in (1, 2, 3)
AND
(
    EXISTS
    (
        SELECT * FROM House
        WHERE Person.ID = House.PersonID
        AND House.Type = 'TOWNHOUSE'
        AND House.Size = 'Medium'
    )
    OR
    EXISTS
    (
        SELECT * FROM Color
        WHERE Person.ID = Color.PersonID
        AND Color.Foreground IN ('Green', 'Blue', 'Purple')
    )
)

我非常感谢您在优化查询时的任何响应。

特别是,有没有办法只使用一个没有任何内部SELECT语句的SELECT语句将查询转换为更有效的查询?

谢谢!

4 个答案:

答案 0 :(得分:4)

这是查询:

SELECT p.* 
FROM Person p
WHERE p.ZipCode LIKE '123%'  AND p.City = 'Washington' AND p.NumberOfHomes in (1, 2, 3) AND
      (EXISTS (SELECT *
               FROM House h
               WHERE p.ID = h.PersonID AND h.Type = 'TOWNHOUSE' AND h.Size = 'Medium'
             ) OR 
       EXISTS (SELECT *
               FROM Color c
               WHERE p.ID = c.PersonID AND c.Foreground IN ('Green', 'Blue', 'Purple')
              )
      );

如果不重写查询,可以使用索引对其进行优化。我建议:

Person(City, ZipCode, NumberOfHomes, Id);
House(PersonId, Type, Size);
Color(PersonID, Foreground)

问题。您确定身份s in the众议院and颜色tables really match back to Person.Id ? Normally, they would have a column called something like PersonId`。

答案 1 :(得分:0)

左连接和检查null将比进行存在检查更快。此外,如果NumberofHomes是一个整数,则BETWEENIN相同。

SELECT p.*
FROM Person p
LEFT JOIN House h
    ON p.ID = h.PersonID
    AND h.Type = 'TOWNHOUSE'
    AND h.Size = 'Medium'
LEFT JOIN Color c
    ON p.ID = c.PersonID
    AND c.Foreground IN ('Green', 'Blue', 'Purple')
WHERE p.ZipCode LIKE '123%'
  AND p.City = 'Washington'
  AND p.NumberOfHomes BETWEEN 1 AND 3
  AND (h.PersonID is not null or c.PersonID is not null)

或者你可以尝试这样的事情......

select t.* 
from (
    select personid from house
    where type = 'townhouse' and size = 'medium'
    union
    select personid from color
    where foreground in ('green','blue','purple')
) pid
cross apply (
    select *
    from person p
    where p.id = pid.personid
      and p.zipcode like '123%'
      and p.city = 'washington'
      and p.numberofhomes between 1 and 3
    ) t
where t.id is not null

优化这些盲人真的很难。根据您的数据分布,上述查询可能会给您带来更好的结果。

答案 2 :(得分:0)

请试试这个:

SELECT p.*
FROM Person p
WHERE Substring(Ltrim(Rtrim(p.ZipCode)),1,3) = '123' AND p.City = 'Washington'AND 
(p.NumberOfHomes=1 or  p.NumberOfHomes=2 or p.NumberOfHomes=3))
AND
(
EXISTS
(
    SELECT 1 FROM House h
    WHERE p.ID = h.PersonID
    AND h.Type = 'TOWNHOUSE'
    AND h.Size = 'Medium'
)
OR
EXISTS
(
    SELECT 1 FROM Color c
    WHERE p.ID = c.PersonID
    AND (c.Foreground ='Green' or c.Foreground='Blue' or  c.Foreground='Purple')
)
);

这也会更好:

SELECT 
    p.*
FROM Person p
Left join House h
    On (p.Id=h.PersonID)
Left join Color c
    On (p.id=c.PersonID)
WHERE Substring(Ltrim(Rtrim(p.ZipCode)),1,3) = '123' AND p.City = 'Washington'AND 
(p.NumberOfHomes=1 or  p.NumberOfHomes=2 or p.NumberOfHomes=3)) and Isnull(h.Type,'') =   'TOWNHOUSE' AND Isnull(h.Size,'') = 'Medium' AND 
(Isnull(c.Foreground,'') ='Green' or Isnull(c.Foreground,'')='Blue' or Isnull(c.Foreground,'')='Purple') and 
(h.PersonID is not null or  c.PersonID is not null);

答案 3 :(得分:-1)

通常优化并具有多个不同的select语句是不同的主题,因为查询优化器(SQL Server)通常会采用您的sql语句并以它认为最合适的方式运行它。

说是,有几种不同的方法可以将你的语句组合成一个sql语句,这是一个例子。这将保留您的人员表并从符合您标准的House或Color表中获取匹配。

<!-- language:SQL-->
SELECT *
FROM Person Left Outer Join House ON Person.ID = House.PersonID Left Outer Join Color ON
Person.ID= Color.PersonID
WHERE (ZipCode LIKE '123%'
    AND City = 'Washington'
    AND Person.NumberofHomes in (1, 2, 3) )
    AND (
        House.Type = 'TOWNHOUSE'
        AND House.Size = 'Medium'
    )
    OR(
         Color.Foreground IN ('Green', 'Blue', 'Purple')
    )

我建议您重新考虑您的模型。例如,具有颜色的PersonID是非常可疑的,因为具有numberofhomes(例如,可以通过House表上具有该人的id的计数来计算)。还有一些其他可疑的规范化属性。不是你问题的一部分,但我认为你可能想要考虑它。