【发布时间】:2019-10-22 15:33:28
【问题描述】:
我有以下表格结构:
tb_学生
CustomerId StudentId StudentName
1 1 Michael
1 2 Sam
2 1 Declan
tb_Contact_Detail
StudentId ContactId CustomerId ContactName Relation
1 1 1 Rory Father
1 2 1 Rachel Mother
tb_Channel
ChannelId ChannelName
1 Emergency
2 GeneralInfo
tb_Contact_Channel_Mapping
CustomerId ChannelId StudentId ContactId
1 1 1 2
1 2 1 2
1 2 1 1
tb_Contact_Fields
CustomerId ContactId ContactType(Phone/SMS/Email)
1 1 Phone
1 1 Email
1 1 SMS
1 2 Email
1 2 SMS
SELECT @EmailCnt = ISNULL(SUM(CASE WHEN field.FieldType = 'Email' THEN 1 ELSE 0 END), 0),
@PhoneCnt = ISNULL(SUM(CASE WHEN field.FieldType = 'Phone' THEN 1 ELSE 0 END), 0),
@SMSCnt = ISNULL(SUM(CASE WHEN field.FieldType = 'SMS' THEN 1 ELSE 0 END), 0)
FROM tb_Students stu WITH (NOLOCK)
INNER JOIN tb_Contact_Detail det WITH (NOLOCK) ON stu.CustomerId = det.CustomerId
AND stu.StudentId = det.StudentId
INNER JOIN tb_Contact_Channel_Mapping map WITH (NOLOCK) ON det.CustomerId = map.CustomerId
AND det.StudentId = map.StudentId
AND det.ContactId = map.ContactId
INNER JOIN tb_Contact_Fields field WITH (NOLOCK) ON det.CustomerId = field.CustomerId
AND det.ContactId = map.ContactId
WHERE stud.CustomerId = @CustomerId
AND map.ChannelId = @ChannelId;
For ChannelId=1, CustomerCode=1
Result id EmailCount 2, PhoneCount 1, SMSCount 2
此查询经常在多个工作流程中使用。然而,现在观察到的问题是,随着学生、联系人和频道的记录不断增加,此查询的结果会变慢并超时。是否有任何性能改进或替代方案可以建议?
【问题讨论】:
-
出于兴趣,你为什么对每张桌子都使用
NOLOCK?我希望 " 此查询的结果会变慢并超时。" 不是原因;因为它很可能会让你的结果出错,而不是更快。 -
不是性能问题,而是小心地将 NOLOCK 溅到各处。这不是一个神奇的快速按钮。它有一些非常严重的副作用。诸如随机返回丢失和/或重复的行之类的事情。提示可以做一连串其他“有趣”的事情。 sentryone.com/blog/aaronbertrand/bad-habits-nolock-everywhere
-
查看查询执行计划,看看是否建议添加任何键或索引。
-
对于手头的任务,是的,随着添加更多行,查询会变慢。我的猜测是你在这里没有一个好的索引策略。也许您可以分享执行计划? brentozar.com/pastetheplan
-
您是否尝试过通过 WHERE ...field.FieldType IN('Email', 'Phone','SMS') 排除记录,可能在某处的索引中使用 FieldType - 只有这些记录在最终输出
标签: sql sql-server