ris*_*ism 7 performance sql-server sql-server-2008-r2 case query-performance
我有以下查询,在少于 100K 行的数据集上运行最多需要 2 秒。
我的 SQL 非常生疏,但这看起来像是做的工作比它应该做的多。任何人都可以提供一些关于在哪里寻找加快速度的指示吗?
SELECT
a.AddressID,
IsPrincipal = CASE
WHEN EXISTS(SELECT TOP 1 1 FROM dbo.Setting s WHERE s.SettingValue = a.AddressID AND s.SettingDefinitionID = 3 AND s.ProfileID = 1)
THEN 1
ELSE 0
END,
IsPickUp = CASE
WHEN EXISTS(SELECT TOP 1 1 FROM dbo.AddressRole ar WHERE ar.AddressID = a.AddressID AND ar.[AddressRoleTypeID] = 2)
THEN 1
ELSE 0
END,
IsSender = CASE
WHEN EXISTS(SELECT TOP 1 1 FROM dbo.AddressRole ar WHERE ar.AddressID = a.AddressID AND ar.[AddressRoleTypeID] = 3)
THEN 1
ELSE 0
END,
IsDelivery = CASE
WHEN EXISTS(SELECT TOP 1 1 FROM dbo.AddressRole ar WHERE ar.AddressID = a.AddressID AND ar.[AddressRoleTypeID] = 4)
THEN 1
ELSE 0
END,
IsReceiver = CASE
WHEN EXISTS(SELECT TOP 1 1 FROM dbo.AddressRole ar WHERE ar.AddressID = a.AddressID AND ar.[AddressRoleTypeID] = 5)
THEN 1
ELSE 0
END
FROM dbo.[Address] AS a
WHERE a.MFTID = '12345'
Run Code Online (Sandbox Code Playgroud)
您可以像这样连接AddressRole和Setting表,而不是对每一行进行这样的查找:
SELECT
a.AddressID,
IsPrincipal = Max(iif(s.SettingValue Is Not Null, 1, 0)),
IsPickUp = Max(iif(ar.AddressRoleTypeID = 2, 1, 0)),
IsSender = Max(iif(ar.AddressRoleTypeID = 3, 1, 0)),
IsDelivery = Max(iif(ar.AddressRoleTypeID = 4, 1, 0)),
IsReceiver = Max(iif(ar.AddressRoleTypeID = 5, 1, 0))
FROM dbo.[Address] AS a
Left Join dbo.Setting As s
On a.AddressID = s.SettingValue
And s.SettingDefinitionID = 3
And s.ProfileID = 1
Left Join dbo.AddressRole As ar
On a.AddressID = ar.AddressID
WHERE a.MFTID = '12345'
Group By a.AddressID;
Run Code Online (Sandbox Code Playgroud)
这应该会减少执行的连接次数,并且不会更改结果集的基数。
我添加了MAX以便我可以做一个GROUP BY,因为我完全期望AddressRole表格中的每一行可能有不止一行Address。通过这种方式,我们将基数保持为与Address表相同,但我们可以查看表中的任何行是否AddressRole包含AddressRoleTypeID我们正在寻找的值。
在MAX和GROUP BY不需要的,如果你的原始查询无子查询TOP返回一行。