【问题标题】:Why is SQL Server database function performing slow | SSRS multi-valued parameter with stored procedure为什么 SQL Server 数据库函数执行缓慢 |带有存储过程的 SSRS 多值参数
【发布时间】:2020-04-23 18:29:11
【问题描述】:

我正在寻找有关使用 SQL Server 时一些有趣问题的见解。

背景

  • 我们在 APS (SQL Server PDW/MPP) 上运行的 SSRS 报告很少
  • 具有嵌入式查询的报表数据集直接在数据库上运行。现在,其中一个较大的表已被拆分为“当前”和“历史”表(“当前”表有最近几年的数据),显然是为了提高这些报告的性能。
  • 我需要更改 SSRS 报告,使相同的报告现在应该根据选择的“年份”作为参数之一重定向到这些表中的任何一个。
  • 我的设计方法:我决定在 SSRS 报告数据集中使用数据库存储过程 (SP),在存储过程中构建所需的逻辑。

问题陈述

  • 顺便说一下,多值参数不会像我想象的那样工作。

  • 当我查看此问题时,这似乎是一个已知问题,并且是 SSRS 支持不佳的功能之一。似乎多值参数中的多个值仅被视为单个值,即使在打印时它们看起来像中的多个值

    val1,val2,val3

  • 以下是我参考的几篇帖子:Link1Link2

  • 然后我决定找到一些解决方法来使其正常工作,遵循上面和下面帖子中的一些建议。

Link3

  • 经过多次尝试,我设法通过构建如下所示的逻辑来实现此功能

    • 第一步:从SSRS,参数改成:

      =Join(Parameters!param_1.Value,"|")
      
    • Step2:使用SP中的一段代码对多值参数进行转换/格式化,并将其存储在一个新的变量(SQLString)中

      --Relevant code:
      
      -- Block of conversion code
      -- to convert/format the multivalued param and store it in a new variable
      -- after this the SQLSTRING variable's final value is set as 
      -- |val1|val2|val3|
      
      -- Relevant where clause
      AND 
          (@SQLString LIKE '%|' + tbl.attr_1 + '|%')  
      
  • 成功了!虽然,警告提到这肯定不是高性能的。 SSRS 报告中的结果很快(尽管这只是一个示例查询)。

  • 现在我决定将“转换代码块”转换为标量函数,如下所示,这样我就可以每次为每个多值参数调用此函数。 Link 4

  • 这也有效,但太慢了(对于只有一个多值参数的相同示例查询,即一次调用此函数)。

问题

  • 我很困惑(我对 SQL Server 内部知识了解不多)为什么将一段代码转换为函数会在这种程度上减慢查询执行速度。

不胜感激。

提前致谢。

【问题讨论】:

  • 领先的通配符会扼杀性能。
  • 从根本上说,像 PDW/MPP 这样的平台不应该要求这些前端杂技来获得所需的性能。该表正在此处“手动”分区。您应该能够使用分布、分区、有序 CCI、非聚集索引在后端透明地实现这一点。这个表有多少行?
  • @avery_larry 是的。但我不明白为什么。
  • @Nick.McDermaid 同意。决策者意识到这一点。但目前已决定将其作为临时解决方案。分布已经到位。并且报告查询在连接多个此类表时会利用这些分布。我将探讨其余部分(分区、有序 cci、非聚集索引)w.r.t。到APS上的这个模型。我在这些领域没有太多经验,在这里不胜感激。该表有 23.42 亿行(拆分为当前和历史之前)。

标签: sql-server reporting-services ssrs-2016


【解决方案1】:

我总是将连接的参数操作到存储过程中的一个表中,然后内部连接到该表。

使用我自己的数据的示例:

我使用的 SSRS 连接:

=Join(Parameters!param_1.Value,"#~--~#")

然后是存储过程:

create proc whatever
@profs varchar(8000)
as

declare @profs_t table (ProfName varchar(70))
declare @delim varchar(10) = '#~--~#'
declare @delimlen int = len(@delim)
declare @idx int = 1 - @delimlen

while charindex(@delim, @profs, @idx + @delimlen) <> 0
    begin
        insert into @profs_t
        select substring(@profs, @idx + @delimlen, charindex(@delim, @profs, @idx + @delimlen) - @idx - @delimlen)
        set @idx = charindex(@delim, @profs, @idx + @delimlen)
    end
insert into @profs_t
select substring(@profs, @idx + @delimlen , len(@profs))

select *
from @profs_t pt
inner join professionals p on p.profname = pt.profname

这会将连接参数从 SSRS 转换为表变量(您可以很容易地使用临时表)。这是相当通用的,可以使用任何分隔符,甚至是多个字符分隔符(如图所示)。我想分隔符也可以作为参数传递给proc。

【讨论】:

  • 感谢您提出另一个实施方案。显然 PDW (docs.microsoft.com/en-us/sql/t-sql/data-types/…) 不支持“表”数据类型,否则我会更早使用它。目前我正在使用/构建一个字符串变量来存储处理多值参数后的结果。问题是,一旦我将这个“处理逻辑”放在一个函数中(以使其可重用于其他多值参数),它就开始运行太慢,而如果这个逻辑在主 StoredProc 中,它运行得很快。我想知道这里发生了什么。
  • 改用“常规”临时表。 . ?
【解决方案2】:

我想我找到了我的问题的答案,如下页所述。 Scaler UDF

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-11-02
    • 2018-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-02
    • 1970-01-01
    • 2013-01-27
    相关资源
    最近更新 更多