Improving Column Grouping Speed in Microsoft Reporting Services - reporting-services

I am doing a large application where I am using column grouping in my reports. Unfortunately, the performance is pitifully slow, and my customer is complaining about it. As an example, if they run a report for a 24 hour period, it takes ~10 minutes to return (~800 display pages of data). If they run it for a month, it may never return!
The query itself for a 24 hour period returns in ~20 seconds. The balance of the time is pivoting and generating the report.
Do you have any suggestions as what I could do?
Thanks!

Check to make sure you are sorting on the report side as opposed to the query side. This can speed things up. Sorting groups or sorting by aggregate values is much simpler in the report than in the query and is frequently more efficient also.
Take a look at these tips for speeding up performance.
Troubleshooting Reports: Report Performance

Reporting Services has three stages in creating a report:
Data retrieval (executing the queries to return the dataset results)
Processing (grouping and aggregating the returned data according to
the report layout)
Rendering (generating the selected output, e.g.
HTML, Excel)
If your query returns data in ~20 seconds but the report takes 10 minutes to render, then the main issue is with the speed of the report processing (rendering is rarely a performance bottleneck), as you rightly assumed. The best way to improve performance is to off load as much of the aggregation as possible to the source database by re-writing your query to do the aggregating there. The database platform is usually much faster at aggregating data than Reporting Services. Ideally you want to return the minimum amount of data required for the report so that it has as little processing to do as possible.
If you have access to the ReportServer database, run this query to confirm where the bottleneck is:
SELECT ItemPath, Format, TimeStart, TimeEnd, TimeDataRetrieval, TimeProcessing, TimeRendering, [Status], ByteCount, [RowCount]
FROM ExecutionLog3
WHERE ItemPath LIKE '%My Report Name%'
TimeDataRetrieval, TimeProcessing and TimeRendering should give you a clear idea of where the problem lies. If the issue is with TimeProcessing then try and rewrite the query to reduce the data for the report and also review the possible design issues to see if any of them apply.

Related

Different datasets for table and graph

I'm showing a table with only actuals from week x, while below the actuals i'm showing a graph with the same data but then over 13 periods (x-13)
Performance wise, would you use 2 datasets for each object? Or would you use 1 dataset and filter the table on the last week?
Thanks!
If the query is pretty intensive, it will obviously be quicker to call it once and filter in the report. Same is true if the connection is slow, or if the server performance is awful.
However, if the client machine runs like a dog (or the report server), then you might fare better calling 2 different queries.

Where to Aggregate Using Microsoft Reporting Services?

I'm working on my first SSRS report and I haven't been able to find general guidelines as to how to create reports. Specifically, I would like to know what the general approach is when aggregate data is needed on a report. For example, let's say I need to show the following in my report:
Pancakes ---34
Eggs----------56
Bacon--------73
I have a several more rows like the above that need to show aggregate data. I'm currently grouping the whole row by type and then on each cell I'm showing a count as follows: [Count(Status)].
My report is already taking 45+ seconds to run. Is it generally preferable to do aggregation like this in the query? Or does this depend on the amount of data being returned? Any pointers are greatly appreciated. Thanks!
As with all SQL answers: it depends.
But generally do your aggregation in SQL. SQL server is much better at performing aggregation than the report layer. Also bringing back less rows will reduce your data transfer and the amount of data which SSRS needs to process. Usually you would only want to do the aggregation at the report layer if there are other constraints which make doing it in the SQL query impossible or if doing so will make the report more difficult to maintain in the future. (There's certainly something to be said for sacrificing a bit of performance in the name of maintainability.) One case would be when you need to display all of the data and returning two datasets is either too complicated or actually slows down the performance of the report.
As a side note, if your report is taking 45+ seconds to run then likely your SQL is not optimized very well or your report is doing a lot of complicated calculations. The more work you can put back on the SQL server the better your performance will be. SQL Server is made for crunching numbers and doing aggregations so certainly let it do what it does best when you can.
YMMV, so always do performance testing for different methods to see what works best.

Sql Statements as Data in mySQL Database

I have to produce a pretty complex report. Without a doubt someone will ask me for the individual records that make up the counts, totals etc.
Im new to mySql. I have tried and found out that I can store Sql statements as data of type Text without any real problems.
Being able to do it, however begs the main question:
Is this a good idea? Is there anything here that will hit me with a "Got ya!"
(Its always what you don't know that gets you, never what you do know)
The report will return Sales Count: 5
I would Live to store "SELECT * FROM Sales WHERE Producer_ID = 34" so I can quickly get to the 34 records that make up the 5 Sales count
Storing SQL queries as data in a SQL DB is sometimes labelled dynamic SQL queries. It is prone to injection issues, and should not be undertaken lightly. I recommend not doing so unless you have a very good reason to do so.

Looking for approach to limit TempDb space needed. Does a VIEW have any place here?

We have a process that executes the following SQL pattern on a very large amount of data:
INSERT INTO Target
SELECT
Col1,Col2,Col33,Col44, (...) Col30
,SUM(Col31)
,SUM(Col32)
FROM
SOURCE
GROUP BY
1,2,3,4 ...30
Because of the large numbers of rows in the Source table and the large number of columns in the Group by clause, this results in very high TEMPDB space usage and on one occasion we ran out of space.
Given that the Business requirements dictate grouping by an usual number of columns, we need to find a way to reduce the amount of TEMPDB space that we use without effecting the performance of the resulting Target table, which serves as our main reporting table.
We were thinking to get the the Reporting Months in the SourceTable and then create a CURSOR in which we individually loop and execute the above SQL only WHERE Source.ReportingMonth = #CurrentReportingMonth from the Cursor and do this until all of the ReportingMonths have been processed. Unfortunately, historical data is allowed to change and so all of the data for each month must be examined each time we process a monthly cycle. The data in each month is approximately teh same volume.
When we told our DBA that this was our intent, his response was "I think that is a very good start, however, if the resultant table is basically used for reporting and not futher aggregation, we would probably be better off just replacing the table with a view since there is very little aggregation actually performed."
My thought is that a view still results in the execution of the SQL and that by converting the SQL to a view, performance could be impacted because the SQL may be executed many times by reports that need the data that used to be stored permanently in a persistent physical table. In SQL Server, are their views that can be persisted for performance reasons to avoid having to execute the SQL multiple times? If we only have one process that runs monthly to populate the Target table, is there any advantage to turning the Target table into a view of the Source table?
Q1: Is our cursoring idea a reasonable approach to pursue to solve the TEMPDB space issue?
Q2: Does a VIEW have any place here?
Note: we also suggested that the users identify if there is data that is "old enough" to be archived.

SSRS Performance

I Have created an SSRS Report for retrieving 55000 records using a Stored Procedure. When
executing from the Stored Proc it is taking just 3 seconds but when executing from SSRS report it is taking more than one minute. How can I solve this problem?
The additional time could be due to Reporting Services rendering the report in addition to querying the data. For example if you have 55,000 rows returned for the report and the report server then has to group, sort and/or filter those rows to render the report then that could take additional time.
I would have a look at the way the data is being grouped and filtered in the report, then review your stored procedure to see if you could offload some of that processing to the SQL code, maybe using some parameters. Try and aim to reduce the the amount of rows returned to the report to be the minimum needed to render the report and preferably try to avoid doing the grouping and filtering in the report itself.
I had such problem because of parameters sniffing in my SP. In SQL Management Studio when I run my SP, I recreated it with new execution plan (and call was very fast), but my reports used old bad plan (for another sequence of parameters) and load time was much longer than in SQL MS.
in the ReportServerDB you will find a table called ExecutionLog. you got to look up the catalog id of your report and check the latest execution instance. this can tell you the break-up of the times taken - for data retrieval, for processing, for rendering etc.
Use the SSRS Performance Dashboard reports to debug your issues.
Archaic question but because things like that are kinda recurring, my "quick and dirty" solution to improve SSRS, which works perfectly on large enterprise environments (I am rendering reports that can have up to 100.000+ lines daily) is to properly set the InteractiveSize of the page (for example, setting it to A4 size -21 cm ). When InteractiveSize is set to 0, then all results are going to be rendered as single page and this literally kills the performance of SSRS. In cases like that, queries that can take a few seconds on your DB can take forever to render (or cause an out of memory exception unless you have tons of redundant H/W on your SSRS server).
So, in cases of queries/ SP's that execute reasonably fast on direct call and retrieve large number of rows, set InteractiveSize and you won't need to bother with other, more sophisticated solutions.
I had a similar problem: a query that returns 4,000 rows and runs in 1 second on it's own was taking so long in SSRS that it timed out.
It turned out that the issue was caused by the way SSRS was handling a multi-valued parameter. Interestingly, if the user selected multiple values, the report rendered quickly (~1 second), but if only a single value was selected, the report took several minutes to render.
Here is the original query that was taking more than 100x longer to render than it should:
SELECT ...
FROM ...
WHERE filename IN (#file);
-- #file is an SSRS multi-value parameter passed directly to the query
I suspect the issue was that SSRS was bringing in the entire source table (over 1 million rows) and then performing a client-side filter.
To fix this, I ended up passing the parameter into the query through an expression, so that I could control the filter myself. That is, in the "DataSet Properties" window, on the "Parameters" screen, I replaced the parameter value with this expression:
=JOIN(Parameters!file.Value,",")
... (I also gave the result a new name: filelist) and then I updated the query to look like this:
SELECT ...
FROM ...
WHERE ',' + #filelist + ',' LIKE '%,' + FILENAME + ',%';
-- #filelist is passed to the query as the following expression:
-- =JOIN(Parameters!file.Value,",")
I would guess that moving the query to a stored procedure would also be an effective way to alleviate the problem (because SSRS basically does the same JOIN before passing a multi-value parameter to a stored procedure). But in my case it was a little simpler to handle it all within the report.
Finally, I should note that the LIKE operator is maybe not the most efficient way to filter on a list of items, but it's certainly much simpler to code than a split-string approach, and the report now runs in about a second, so splitting the string didn't seem worth the extra effort.
Obviously getting the report running correctly (i.e. taking the same order of magnitude of time to select the data as SSMS) would be preferable but as a work around, would your report support execution snapshots (i.e. no parameters, or parameter defaults stored in the report)?
This will allow a scheduled snapshot of the data to be retrieved and stored beforehand, meaning SSRS only needs to process and render the report when the user opens it. Should reduce the wait down to a few seconds (depending on what processing the report requires. YMMV, test to see if you get a performance improvement).
Go to the report's properties tab in Report manager, select Execution, change to Render this report from a report execution snapshot, specify your schedule.
The primary solution to speeding SSRS reports is to cache the reports. If one does this (either my preloading the cache at 7:30 am for instance) or caches the reports on-hit, one will find massive gains in load speed.
Please note that I do this daily and professionally and am not simply waxing poetic on SSRS
Caching in SSRS
http://msdn.microsoft.com/en-us/library/ms155927.aspx
Pre-loading the Cache
http://msdn.microsoft.com/en-us/library/ms155876.aspx
If you do not like initial reports taking long and your data is static i.e. a daily general ledger or the like, meaning the data is relatively static over the day, you may increase the cache life-span.
Finally, you may also opt for business managers to instead receive these reports via email subscriptions, which will send them a point in time Excel report which they may find easier and more systematic.
You can also use parameters in SSRS to allow for easy parsing by the user and faster queries. In the query builder type IN(#SSN) under the Filter column that you wish to parameterize, you will then find it created in the parameter folder just above data sources in the upper left of your BIDS GUI.
[If you do not see the data source section in SSRS, hit CTRL+ALT+D.
See a nearly identical question here: Performance Issuses with SSRS
Few things can be done to improve the performance of the report which are as below:
1. Enable caching on the report manager and set a time period to refresh the cache.
2. Apply indexing on all the backend database tables that are used as a source in the report, although your stored procedure is already taking very less time in rendering the data but still applying indexing can further improve the performance at the backend level.
3. Use shared datasets instead of using embedded datasets in the report and apply caching on all these datasets as well.
4. If possible, set the parameters to load default values.
5. Try to reduce the data that is selected by the stored procedure, e.g. if the report contains historical data which is of no use, a filter can be added to exclude that data.
I experienced the same issue. Query ran in SQL just fine but was slow as anything in SSRS. Are you using an SSRS parameter in your dataset? I've found that if you use the report parameter directly in certain queries, there is a huge performance hit.
Instead, if you have a report parameter called #reportParam, in the dataset, simply do the following:
declare #reportParamLocal int
set #reportParamLocal = #reportParam
select * from Table A where A.field = #reportParam
It's a little strange. I don't quite know why it works but it does for me.
One quick thing you may want to look at is whether elements on your report could be slowing down the execution.
For example i have found massive execution time differences when converting between dateTimes. Do any elements on report use the CDate function? If so you may want to consider doing your formatting at the sql level.
Conversions in general can cause a massive slow down so take the time to look into your dataset and see what may be the problem.
This is a bit of a mix of the answers above, but do your best to get the data back from your stored procedure in the simplest and most finished format. I do all my sorting, grouping and filtering up on the server. The server is built for this and I just let reporting services do the pretty display work.
I had the same issue ... it was indeed the rendering time but more specifically, it was because of the SORT being in SSRS. Try moving your sort to the stored procedure and removing any SORT from the SSRS report. On 55K rows, this will improve it dramatically.
Further to #RomanBadiornyi's answer, try adding
OPTION (RECOMPILE)
to the end of your main query in the stored procedure.
This will ensure the query is recompiled for different parameters each time, in case different parameters need a different execution plan.