[英]SQL Server T-SQL 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語句將查詢轉換為更有效的查詢?
謝謝!
這是查詢:
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)
但問題是。 你確定的ID s in the
家and
顏色tables really match back to
Person.Id ? Normally, they would have a column called something like
? Normally, they would have a column called something like
PersonId` ? Normally, they would have a column called something like
。
左連接和檢查null將比進行存在檢查更快。 此外,如果NumberofHomes是一個整數,則BETWEEN
將與IN
相同。
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
優化這些盲人真的很難。 根據您的數據分布,上述查詢可能會給您帶來更好的結果。
請試試這個:
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);
通常優化和具有多個不同的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的計數來計算)。 還有一些其他可疑的規范化屬性。 不是你問題的一部分,但我認為你可能想要考慮它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.