Dynamics CRM in the Field

Information from the Microsoft Dynamics CRM PFE team working in the field

Speeding up sluggish CRM reports that use date/time parameters

Speeding up sluggish CRM reports that use date/time parameters

Rate This
  • Comments 2

As many of you may know, when writing custom reports for CRM 4.0 you are required to use the filtered views. The upside is filteredViews make security a snap for reporting against CRM data, and they offer a consistent dataset between the user will see in the CRM UI and what they will see in CRM reports. For instance, when a CRM user has access to CRM data via their role privileges they will see that same data in a report, but if the user doesn't have access to the data in CRM they won't be able to surface that data in a report either. What you may have noticed when writing and running reports against filtered views is a sluggish response when selecting, filtering, or ordering by date/time values in your report. Let's break down what's going on and what you can do about it:

Why is this?

All date/time data in CRM are stored in the database as UTC values. To make sure the times are displayed to users in their local timezone, a SQL User Defined Function (UDF) is used to convert the values from the database tables to local time in the filtered views. When running a query via the filtered views against a large dataset, every record in the dataset must be evaluated by this function to determine the local date/time value, which can add significant overhead to your report.

What can I do about it?

Because all the date/time data values are stored in UTC format, reports that query against the UTC time will circumvent the UDF, and the query time will be reduced. However, this will alter the data returned by the query and could also impact your conditions if the report contains a date/time parameter . The solution we will explore in this article is:

  • Query all date/time data using only the UTC columns
  • Convert any input parameters, or input date/time data from local time to UTC Time, which will make sure we are retrieving the correct data
  • Convert any output data in the SSRS report to display the UTC date/time

How can I take advantage of reporting in UTC without having to teach my users how do timezone conversions?

You can use the same functions that CRM utilizes to convert the date/time values, however, instead of having SQL do this conversion for all the data, we can convert the final dataset making the report run much quicker. The process we're going to use is:

  • When the report is initially loaded we're going to run the query in Fig 1 (at the bottom of this posting) which will retrieve the minutes needed to convert a local time to UTC as well as the minutes needed to convert a UTC time to the users local time. Both of these parameters will be available in the report (@minsFromLocalToUTC and @minsFromUTCToLocal)
  • Any parameters or inputs that will be used in the "Where" condition will be in local datetime format if the user selects them. These must be converted in your SQL query to UTC.
  • Any data outputs will be retrieved in UTC time and must be converted to local time in your SSRS report, using an SSRS expression, so the user see's the date/time value in their local timezone.

Example:

In this sample we have a report that will fetch a list of accounts with the account name, modified date/time, and who modified the record. The user running the report selects a beginning date and ending datetime as a parameter. Your two parameter names in the report are named: "@beginDateTime" and "@endDateTime".



Your current TSQL statement:

  • select name, modifiedbyname , modifiedby, modifiedon, accountid
    from FilteredAccount
    where modifiedon Between @beginDateTime and @endDateTime
    order by modifiedon desc


To convert the report over to using UTC a few modifications need to be done in the report.

  1. Open your report for editing in Visual Studio 2008 Business Intelligence Designer
    • Add a new dataset to retrieve our conversion values:
    • Under the "Report Data" pane right click the "CRM" datasource and select "Add Dataset"

      image

    • In the Dataset properties page:
      • name your new dataset "TimezoneConversions"
      • Keep the "Data Source" value the same (CRM)
      • Select "Text" query type
      • Paste in the query text from Fig 1. (at the bottom of this post)
      • Press the OK button to create the new Dataset which will contain your two conversion values
  2. Add a parameter in your report that contains the minutes required to convert UTC time to local time.
    • Under the "Report Data" pane right click "Parameters" and select "Add Parameter"

      clip_image002

    • In the Report Parameter properties page
      • name your new parameter "MinutesToUTC"
      • Set the prompt to: "MinutesToUTC"
      • Change the DataType value to "Integer"
      • Change the parameter visibility to "Hidden"
      • In the left pane click "Default Values"
      • Change the default value to "Get values from a query"
      • In the dataset drop down select the dataset we created earlier "TimezoneConversions"
      • In the Value field drop down select "ToUTCTime"
      • Press Ok to create your new parameter
  3. Modify your query to query the UTC values instead of the local values
    • Right-click the dataset that contains your account query
    • Change your account query from what it was at the top of the example to:
    • select name, modifiedbyname, modifiedby, modifiedonUTC as modifiedon, accountid
      from FilteredAccount
      where modifiedonUTC Between DateAdd(mi,@MinutesToUTC,@beginDateTime) and DateAdd(mi,@MinutesToUTC,@endDateTime)
      order by modifiedonUTC desc
    • Notice how we've added a "DateAdd" expression. This is going to take the offset to UTC and add it to the users local time parameters so that the query is run in UTC time instead of local. Also, notice how all date/time references now specifically call out UTC - this is important and will also help improve query time. I've also used the alias of 'modifiedOn' for the new modifiedOnUTC value to save the effort of updating the report - anywhere in the report that references modifiedOn will continue to function properly.
    • Important: you should change all date/time references over to UTC and convert them to reap the benefits of this change. If you still have some in the select statement you'll get better performance but not as good as if you removed all local date/time references
    • Now, your "where" condition will be evaluated in UTC time (based on the users local time parameter) and all the data will come back to your report in UTC time.
  4. Add a parameter in your report that contains the minutes required to convert UTC time to local time.
    • Under the "Report Data" pane right click "Parameters" and select "Add Parameter" to open the Report Parameter properties page

      clip_image002

    • In the Report Parameter properties page
      • name your new parameter "MinutesToLocal"
      • Set the prompt to: "MinutesToLocal"
      • Change the DataType value to "Integer"
      • Change the parameter visibility to "Hidden"
      • In the left pane click "Default Values"
      • Change the default value to "Get values from a query"
      • In the dataset drop down select the dataset we created earlier "TimezoneConversions"
      • In the Value field drop down select "ToLocalTime"
      • Press Ok to create your new parameter
  5. Modify the output in the report to convert your date/time values to local time from UTC
    • In the output dataset within the report you are going to have SSRS convert the time from the query, which will be in UTC, over to use local time.
    • Find the cell that contains the modifiedOn data and right-click it.
    • Select "Expression" to open the expression editor, notice the value now is =Fields!ModifiedOn
    • Change the expression to read:
    • =DateAdd(DateInterval.Minute,Parameters!MinutesToLocal.Value,Fields!ModifiedOn.Value)
    • This expression will add the time retrieved in our new parameter to the modifiedOnUTC dates, which will convert them to local time.
  6. You've now successfully converted your report over to using UTC instead of local times. The measure of success is:
    • Your report values should stay exactly the same as they were prior to the switchover
    • You should notice your report runs quite a bit faster because you are no longer having SQL do all the heavy lifting against the large dataset.

 

  • Note: for this example in a test system I collected some statistics:
    • Before modification: CPU time = 656 ms, duration = 796 ms, reads = 23723
    • After modification: CPU time = 157 ms, duration = 295 ms, reads = 14636
    • Our net improvement, even on a small dataset and simple query was impressive:
      • CPU time was reduced by 499 milliseconds
      • Reads were reduced by 9087
      • Duration was reduced by 501 milliseconds

 

Fig1. TSQL query to retrieve the current CRM users timezone information

Select
DATEDIFF(mi, '1/15/2011 00:00:00.000',
dbo.fn_UTCToTzSpecificLocalTime(
'1/15/2011 00:00:00.000',
us.TimeZoneBias,
us.TimeZoneDaylightBias,
us.TimeZoneDaylightYear,
us.TimeZoneDaylightMonth,
us.TimeZoneDaylightDay,
us.TimeZoneDaylightHour,
us.TimeZoneDaylightMinute,
us.TimeZoneDaylightSecond,
0,
us.TimeZoneDaylightDayOfWeek,
us.TimeZoneStandardBias,
us.TimeZoneStandardYear,
us.TimeZoneStandardMonth,
us.TimeZoneStandardDay,
us.TimeZoneStandardHour,
us.TimeZoneStandardMinute,
us.TimeZoneStandardSecond,
0,
us.TimeZoneStandardDayOfWeek)) as ToLocalTime,
DATEDIFF(mi, '1/15/2011 00:00:00.000',
dbo.fn_TzSpecificLocalTimeToUTC(
'1/15/2011 00:00:00.000',
us.TimeZoneBias,
us.TimeZoneDaylightBias,
us.TimeZoneDaylightYear,
us.TimeZoneDaylightMonth,
us.TimeZoneDaylightDay,
us.TimeZoneDaylightHour,
us.TimeZoneDaylightMinute,
us.TimeZoneDaylightSecond,
0,
us.TimeZoneDaylightDayOfWeek,
us.TimeZoneStandardBias,
us.TimeZoneStandardYear,
us.TimeZoneStandardMonth,
us.TimeZoneStandardDay,
us.TimeZoneStandardHour,
us.TimeZoneStandardMinute,
us.TimeZoneStandardSecond,
0,
us.TimeZoneStandardDayOfWeek))
as ToUTCTime
FROM FilteredUserSettings us where systemuserid = dbo.fn_FindUserGuid()
  • This system makes one very important assumption: that all dates shown in the report or needing conversion in the report are in the same daylight savings bias.  In the example above, the term January 15th is hard coded into the TimezoneConversions dataset and subsequently into the MinutesToUTC parameter which is used then for conversion.  This query should accept an input parameter, perhaps @beginDateTime, as the date which the function uses to calcuate MinutesToUTC.  However, it is evident even in this scenario that the beginDateTime and the endDateTime could have two different biases.  

    In many reports it is common to have multiple dates listed.  This is another scenario in which only have one MinutesToUTC parameter is limiting.  If one date is in daylight savings time and another is not, one of them will be wrong.

    This is a clever idea, and I may implement it in the right circumstances, but I don't think that it is as useful as adverstised.  At least not in the countries which observe daylight savings.

  • @DoingThisForAWhile - good observation.  You're correct, some additional logic could be added to individually adjust each date/time value on the report. Especially relevant with the daylight savings time shift this past weekend.  I've seen customers hard code their offsets in the report before or report in UTC to make the reports run quicker and the intent was to offer another way that would be more dynamic on a per user basis. This is not quite a one size fits all solution - and if we can find a way to write a step-by-step posting that could be applied to all reporting in which all the date/times would be masked we'll post one.  

    I'll look to try and revisit this posting to account for DST in each value - but it will be a much more extensive posting in which I may have to re-write fn_UTCToTzSpecificLocalTime such that it could be used in each SSRS dataset and also recreate this functionality to be used within the report as an SSRS function.  Thanks for pointing this out!

Page 1 of 1 (2 items)
Leave a Comment
  • Please add 7 and 1 and type the answer here:
  • Post