sql-server - 如何使带有多值参数的查询运行得更快?
问题描述
我有以下运行非常缓慢的查询:
SELECT
DISTINCT a.Role as Role
FROM
[Table_A] a
JOIN
[Table_B] b ON (a.Key = b.Key)
WHERE
b.Date BETWEEN @StartDate AND @EndDate
AND ISNULL(a.ID, -1) IN (@People)
变量的值和@StartDate
来自SSRS 报告中的参数。日期参数只是日期。该参数是一个多值参数。@EndDate
@People
@People
问题是@People
包含超过 3000 个值。所以查询必须使用该IN
子句来完成所有操作。在 SSRS 中运行它时,这真的会减慢我的查询速度。
我想使用 exists 子句来替换该IN
子句,但我似乎无法让它在这种情况下工作。我需要以某种方式从子句中的@People
变量中选择值EXISTS
并将其连接回第一个表,但我什至不知道这是否可能。
也许我在尝试EXISTS
在这种情况下使用时走错了方向。但我仍然需要修复查询,以便它运行得更快。
有人能帮忙吗?
解决方案
ISNULL(a.ID, -1)
将使查询成为非 SARGable。最好使用(a.ID IN (@People) OR a.ID IS NULL)
,但是,IN
具有这么多参数的 an 不太可能运行良好。
我在这里在内存上运行(我家里没有 SSRS)但是如果我记得 SSRS 用多值参数做了一些“魔术”并且IN
不能很好地扩展。也许您最好尝试使用一个EXISTS
和一个分离器(例如DelimitedSplit8k
)。此特定示例依赖于@People
少于 8000 个字符。
SELECT DISTINCT a.Role
FROM [Table_A] a
JOIN [Table_B] b ON a.Key = b.Key
WHERE b.Date BETWEEN @StartDate AND @EndDate
AND (EXISTS (SELECT 1
FROM dbo.DelimitedSplit8K(@People,',') DS
WHERE DS.Item = a.ID)
OR a.ID IS NULL);
然而,考虑到序数位置在这里并不重要,那么其他拆分器是可用的。例如XML 拆分器。
为了完整起见,一个快速编写的 XML 拆分器函数:
CREATE FUNCTION dbo.XMLSplitter (@DelimitedString varchar(MAX))
RETURNS TABLE AS RETURN
SELECT n.d.value('.','varchar(MAX)') AS Item
FROM (VALUES(CONVERT(xml,'<d>'+ REPLACE(@DelimitedString,',','</d><d>') + '</d>'))) V(X)
CROSS APPLY V.X.nodes('d') n(d);
GO
添加了一个没有函数的完整示例:
SELECT DISTINCT a.Role
FROM [Table_A] a
JOIN [Table_B] b ON a.Key = b.Key
WHERE b.Date BETWEEN @StartDate AND @EndDate
AND (EXISTS (SELECT 1
FROM (VALUES(CONVERT(xml,'<d>'+ REPLACE(@DelimitedString,',','</d><d>') + '</d>'))) V(X)
CROSS APPLY V.X.nodes('d') n(d)
WHERE n.d.value('.','varchar(MAX)') = a.ID)
OR a.ID IS NULL);
推荐阅读
- react-native - 反应原生地图 mapView maxZoomLevel 意外行为
- sql - 在 SQL Server 中格式化 Datetime2
- symfony - Symfony2 重新组织配置文件:parameters.dist.yml 问题
- python - 当我在 arduino 中使用 pyserial 时,为什么会出现 Windows 错误 2?
- android - Cordova 构建 Android 返回错误任务':transformDexArchiveWithExternalLibsDexMergerForArmv7Debug'的执行失败
- ios - 如何在 SwiftUI 中制作水平列表?
- linux - linux中的排序命令不能“正确”工作
- docker - 是否有 docker 图像标记而不依赖于图像 ID
- sql-server - SQL Server 中的 MD5 哈希
- typescript - 发布到 Azure 的问题:当“--module”为“无”时无法使用导入