优化 SQL Server 2008 查询
Posted
技术标签:
【中文标题】优化 SQL Server 2008 查询【英文标题】:Optimize SQL Server 2008 query 【发布时间】:2017-02-13 03:11:52 【问题描述】:更新:编辑了表格别名。
我正在尝试查找是否可以重写以下查询以提高性能。我们最近开始注意到对查询的巨大性能影响。 Person 表接近 1000 万,Contact 表接近 1700 万 记录。
SELECT
ID, NAME, DEPARTMENT,
CASE
WHEN PrimaryContact = 'MOBILE'
THEN (SELECT TOP 1 MOBILE
FROM CONTACT
WHERE ContactType = 'MOBILE' AND CONTACT.PID = PERSON.PID)
ELSE (SELECT TOP 1 HOME
FROM CONTACT
WHERE CONTACTTYPE = 'HOME' AND CONTACT.PID = PERSON.PID),
FROM
PERSON
WHERE
DEPARTMENT = @DEPARTMENT
每个人都可以在联系人表中拥有一个/多个手机/家庭电话号码。根据主要联系人类型,它应该只获取一个基于PrimaryContact
类型的电话号码。
另外,我们还计划基于Department
对Person
表进行分区。
任何提高整体性能的建议将不胜感激。
谢谢
【问题讨论】:
您的查询在语法上远非正确,以至于没有意义。DETAILS
是什么?
对不起,那是 PERSON.PID 而不是 DETAILS.PID
您是否查看过此查询的执行计划?他们显示什么?另外:您的表结构是什么,已经存在哪些索引?
【参考方案1】:
对于这个查询:
SELECT p.ID, p.NAME, p.DEPARTMENT,
(CASE WHEN p.PrimaryContact = 'MOBILE'
THEN (SELECT TOP 1 c.MOBILE
FROM CONTACT c
WHERE c.ContactType = 'MOBILE' AND c.PID = p.PID
)
ELSE (SELECT TOP 1 c.HOME
FROM CONTACT c
WHERE c.CONTACTTYPE = 'HOME' AND c.PID = p.PID
END)
FROM PERSON p
WHERE p.DEPARTMENT = @DEPARTMENT;
您应该从索引开始:person(department, primarycontact, pid)
和 contact(pid, contacttype, home, mobile)
。
通常,当您使用TOP
时,您将有一个ORDER BY
子句。
【讨论】:
谢谢,我会添加索引并检查性能。还有其他重写查询的范围吗?【参考方案2】:首先为什么你需要1000万条记录?(分页?)
你可以像这样重写你的查询,修复错误,清除缓存然后运行。
SELECT
ID, NAME, DEPARTMENT,
(SELECT TOP 1 CASE when ContactType='MOBILE' then MOBILE else Home end
FROM dbo.CONTACT with (nolock)
WHERE CONTACT.PID = PERSON.PID
and ( (PrimaryContact = 'MOBILE' and ContactType = 'MOBILE') or (PrimaryContact != 'MOBILE' and ContactType = 'Home')) )
FROM
dbo.PERSON P with (nolock)
WHERE
DEPARTMENT = @DEPARTMENT
即使您可以使用具有相似条件的内部连接并检查自己。
我的索引建议,
clustered index on person.PID
clustered index on contact.PID
non clustered index on person.DEPARTMENT include(name,PrimaryContact)
non clustered index on contact.ContactType include(MOBILE,Home)
【讨论】:
以上是关于优化 SQL Server 2008 查询的主要内容,如果未能解决你的问题,请参考以下文章
SQL Server查询优化器执行计划“语句提前终止的原因:超时”