Sql server 如何使多值参数查询运行得更快?

Sql server 如何使多值参数查询运行得更快?,sql-server,optimization,ssrs-2008,Sql Server,Optimization,Ssrs 2008,我的以下查询运行速度非常慢: 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和@EndDate以及@People的值来自SSRS报告中的参数。日

我的以下查询运行速度非常慢:

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和@EndDate以及@People的值来自SSRS报告中的参数。日期参数只是日期。@People参数是一个多值参数

问题是@People包含3000多个值。因此,查询必须使用IN子句遍历所有内容。在SSRS中运行查询时,这会非常非常慢

我想使用exists子句来替换IN子句,但在这种情况下,我似乎无法使其起作用。我需要从EXISTS子句中的@People变量中选择值并将其连接回第一个表,但我甚至不知道这是否可行

也许我尝试使用这个场景中的EXISTS时走错了方向。但我仍然需要修复查询,以便它运行得更快

有人能帮忙吗?

ISNULLa.ID,-1将使查询不可搜索。您最好在@People中使用a.ID,或者a.ID为NULL,但是,具有这么多参数的IN不太可能运行良好

我在内存上运行,我家里没有SSR,但如果我回忆起来,SSR对多值参数有一些魔力,并且在这方面不能很好地扩展。也许您最好尝试使用EXISTS和拆分器,例如。这个具体的例子依赖于@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拆分器函数:

添加了一个没有函数的完整示例:

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);

你可以通过以下方式发布执行计划:这是不需要的吗?之后在哪里?@scsimon,谢谢。这是一个错误,我删除了额外的AND@OhSoConfused我无法获得执行计划,因此我需要在没有它的情况下获得帮助。表中有哪些索引?这个解决方案对我来说非常有用,但问题是我无法实现自定义函数。我需要使用某种select语句以某种方式将逗号分隔的值拆分。此外,我也不能使用内置的STRING_SPLIT函数,因为我需要将数据库兼容地设置为130,这也是由于权限问题而无法做到的。我很想使用上面的解决方案,但如何仅使用select语句拆分字符串?@Zolt XML拆分器的代码在我的答案中,您可以很容易地将其直接放入主查询中,而我只是将其拆分,以便可以轻松地重用。你试过了吗?您遇到了什么问题?如果我在SSMS中运行您的解决方案,它会起作用,但是当我将查询放入SSRS中,运行报告,并为@DelimitedString选择多个选项时,SSRS会给出以下错误:dataset replace功能的查询执行失败需要3arguments@Zolt试一试以上。否则,您可能希望创建一个SP,SSRS报告可以使用该SP强制它提供分隔列表,而不是替换变量的名称。您不需要像这样组合查询。我以前已经做过了。正如我之前提到的,我让它在SSMS中工作,但不在SSRS中工作。问题是我需要添加=JoinParameters!Label,表示使用上述查询的参数中的参数值。这样做可以让一切顺利。
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);