我创建了一个 SSRS 报告,用于使用存储过程检索 55000 条记录。从存储过程执行时只需 3 秒,但从 SSRS 报告执行时需要一分钟以上。我怎么解决这个问题?
14 回答
额外的时间可能是由于 Reporting Services 除了查询数据之外还呈现报表。例如,如果您为报表返回了 55,000 行,然后报表服务器必须对这些行进行分组、排序和/或过滤以呈现报表,那么这可能需要额外的时间。
我会看看数据在报告中的分组和过滤方式,然后查看您的存储过程,看看您是否可以将一些处理卸载到 SQL 代码,也许使用一些参数。尝试并旨在将返回到报表的行数减少到呈现报表所需的最小值,并且最好尽量避免在报表本身中进行分组和过滤。
由于我的 SP 中的参数嗅探,我遇到了这样的问题。在 SQL Management Studio 中,当我运行我的 SP 时,我使用新的执行计划重新创建它(并且调用非常快),但我的报告使用旧的错误计划(用于另一个参数序列)并且加载时间比 SQL MS 中长得多。
在 ReportServerDB 中,您将找到一个名为 ExecutionLog 的表。您必须查找报告的目录 ID 并检查最新的执行实例。这可以告诉您所用时间的细分 - 用于数据检索、处理、渲染等。
使用SSRS 性能仪表板报告来调试您的问题。
我遇到了类似的问题:返回 4,000 行并在 1 秒内自行运行的查询在 SSRS 中花费了很长时间,以至于超时。
事实证明,这个问题是由 SSRS 处理多值参数的方式引起的。有趣的是,如果用户选择了多个值,报告会快速呈现(约 1 秒),但如果只选择一个值,则报告需要几分钟才能呈现。
这是原始查询的渲染时间超过了应有的 100 倍:
SELECT ...
FROM ...
WHERE filename IN (@file);
-- @file is an SSRS multi-value parameter passed directly to the query
我怀疑问题在于 SSRS 引入了整个源表(超过 100 万行),然后执行客户端过滤器。
为了解决这个问题,我最终通过表达式将参数传递到查询中,这样我就可以自己控制过滤器。也就是说,在“数据集属性”窗口的“参数”屏幕上,我将参数值替换为以下表达式:
=JOIN(Parameters!file.Value,",")
...(我还给结果起了一个新名称:filelist),然后我更新了查询,如下所示:
SELECT ...
FROM ...
WHERE ',' + @filelist + ',' LIKE '%,' + FILENAME + ',%';
-- @filelist is passed to the query as the following expression:
-- =JOIN(Parameters!file.Value,",")
我猜想将查询移动到存储过程也是缓解问题的有效方法(因为 SSRS 在将多值参数传递给存储过程之前基本上会执行相同的 JOIN)。但就我而言,在报告中处理这一切要简单一些。
最后,我应该指出,LIKE 运算符可能不是过滤项目列表的最有效方法,但它的编码肯定比拆分字符串方法简单得多,并且报告现在运行大约一秒钟,因此拆分字符串似乎不值得付出额外的努力。
过时的问题,但因为这样的事情有点反复出现,我改进 SSRS 的“快速而肮脏”的解决方案,它在大型企业环境中完美运行(我正在渲染每天最多可以有 100.000 多行的报告)是正确设置InteractiveSize页面的大小(例如,将其设置为 A4 尺寸 -21 cm )。当 InteractiveSize 设置为 0 时,所有结果都将呈现为单页,这实际上会扼杀 SSRS 的性能。在这种情况下,在您的数据库上可能需要几秒钟的查询可能需要永远呈现(或导致内存不足异常,除非您的 SSRS 服务器上有大量冗余硬件)。因此,如果查询/SP 在直接调用时执行速度相当快并检索大量行,请设置 InteractiveSize,您将无需为其他更复杂的解决方案而烦恼。
我遇到了同样的问题。查询在 SQL 中运行得很好,但在 SSRS 中运行速度很慢。您是否在数据集中使用 SSRS 参数?我发现如果您在某些查询中直接使用报告参数,则会对性能造成巨大影响。
相反,如果您在数据集中有一个名为 @reportParam 的报表参数,只需执行以下操作:
declare @reportParamLocal int
set @reportParamLocal = @reportParam
select * from Table A where A.field = @reportParam
这有点奇怪。我不太清楚它为什么有效,但它对我有用。
显然,让报告正确运行(即花费相同数量级的时间来选择与 SSMS 相同的数据)将是可取的,但作为一种解决方法,您的报告是否支持执行快照(即没有参数,或报告中存储的参数默认值)?
这将允许预先检索和存储数据的计划快照,这意味着 SSRS 只需要在用户打开报告时处理和呈现报告。应该将等待减少到几秒钟(取决于报告需要什么处理。YMMV,测试看看你是否获得了性能改进)。
转到报表管理器中的报表属性选项卡,选择执行,更改为从报表执行快照呈现此报表,指定您的计划。
加速 SSRS 报告的主要解决方案是缓存报告。如果这样做(例如,我在早上 7:30 预加载缓存)或缓存命中的报告,则会发现加载速度大幅提升。
请注意,我每天都在专业地做这件事,而不是简单地在 SSRS 上打蜡
在 SSRS 中缓存 http://msdn.microsoft.com/en-us/library/ms155927.aspx
预加载缓存 http://msdn.microsoft.com/en-us/library/ms155876.aspx
如果您不喜欢需要很长时间的初始报告并且您的数据是静态的,即每日总账等,这意味着数据在一天内相对静态,您可以增加缓存寿命。
最后,您还可以选择让业务经理改为通过电子邮件订阅接收这些报告,这将向他们发送一个时间点 Excel 报告,他们可能会发现该报告更容易、更系统。
您还可以在 SSRS 中使用参数,以便用户轻松解析并加快查询速度。在您希望参数化的过滤器列下的查询生成器类型 IN(@SSN) 中,您将在 BIDS GUI 左上角的数据源上方的参数文件夹中找到它。[如果您在 SSRS 中看不到数据源部分,请按 CTRL+ALT+D。
在此处查看几乎相同的问题:SSRS 的性能问题
可以做以下几件事来提高报表的性能: 1. 在报表管理器上启用缓存并设置刷新缓存的时间段。2. 对报表中用作源的所有后端数据库表应用索引,尽管您的存储过程在呈现数据方面已经花费了非常少的时间,但仍然应用索引可以进一步提高后端级别的性能。3. 使用共享数据集而不是使用报表中的嵌入数据集,并对所有这些数据集应用缓存。4. 如果可能,将参数设置为加载默认值。5. 尽量减少存储过程选择的数据,例如,如果报告中包含无用的历史数据,可以添加过滤器以排除该数据。
您可能想要快速查看的一件事是您的报告中的元素是否会减慢执行速度。
例如,我在 dateTimes 之间转换时发现了巨大的执行时间差异。报告中的任何元素是否使用 CDate 函数?如果是这样,您可能需要考虑在 sql 级别进行格式化。
一般来说,转换可能会导致速度大幅下降,因此请花时间查看您的数据集,看看可能是什么问题。
这有点混合了上面的答案,但尽最大努力以最简单和最完整的格式从存储过程中获取数据。我在服务器上进行所有的排序、分组和过滤。服务器是为此而构建的,我只是让报告服务完成漂亮的显示工作。
除了@RomanBadiornyi 的回答,尝试添加
OPTION (RECOMPILE)
到存储过程中的主查询结束。
这将确保每次为不同的参数重新编译查询,以防不同的参数需要不同的执行计划。
我有同样的问题......这确实是渲染时间,但更具体地说,这是因为 SORT 在 SSRS 中。尝试将排序移动到存储过程并从 SSRS 报告中删除任何排序。在 55K 行上,这将显着改善它。