June 2004 - Posts

Tips for Optimising Reporting Services Performance from tudortr

tudortr has some tips on measuring and improving Reporting Services performance. I heartily agree with number 1: optimise your queries. I've found that using a) proper indexes and b) creating intermediate tables where necessary (possibly containing summarised data from a month that is reported in many different reports, rather than going to the transaction-level original data table, for instance) are the best things I can do to improve performance on my reports.

Media Center Theme for Windows XP

Stefano and Girish inform us that the official Windows Media Center theme (called Royale) can be used on Windows XP. Cool!

I like tweaking my colors but am not willing to load themes from 3rd-party sites on my work PC (or don't want to get busted), so it's nice to have an option. There's instructions on where to copy the theme to in the RAR file, which can be downloaded from Winbeta.

UPDATE: Stefano alerts us that the theme has been officially released (called “Energy Blue“), and can be got here. You'll have to extract the relevant files with WinRAR and copy them manually to your Resources directory, though, as the installer is designed for Tablet PC's only.

Reporting Services SP1 - Installed

Reporting Services SP1 is installed, the installation went really well, and one feature that was in the beta is back: Excel "groups" (the plus/minus rollups in Excel). Believe it or not, this was one of the things that got my boss excited about Reporting Services as many of our managers are familiar with Excel, and when it dropped off in the RTM I had to go through and create some copies of reports specifically for an Excel export.

One strange thing is that there seems to be at least two means of creating expandable groups/hiding report items in the designer, for display in a browser. One way is to set the whole group to being hidden, and set a textbox as a toggle item in the "Grouping and Sorting Properties" dialog (figure 1), another is to set report row(s) as being hidden, toggled by the same textbox (figure 2).

Reporting Services Report Designer 'Grouping and Sorting Properties' dialog (Visibility tab)
Figure 1
Reporting Services Report Designer Row Properties Property Grid
Figure 2

 

The second method creates the Excel "groups" that made me and my boss so happy. I did have a small problem with some wording in the Reporting Services SP1 readme that said:

This service pack is independent of Service Pack 4 (SP4) for SQL Server 2000. If you are installing Reporting Services SP1 after SQL Server SP4 is released, Microsoft recommends that you apply SP4 first.

A search at Microsoft's "Service Packs for SQL Server" (http://www.microsoft.com/sql/downloads/servicepacks.asp) site showed there isn't any SQL Server 2000 SP4, yet, but I found clarification on the newsgroups at http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&frame=right&th=f7246d07373b6bb2&seekm=%23koDNGiWEHA.644%40tk2msftngp13.phx.gbl#link3 which had:

The readme was not meant to imply that you need to have SQL Server SP4
before applying Reporting Services SP1. You can apply Reporting Services SP1
now and then later apply SQL Server SP4 when it is released.

The newsgroups also saved me some headache with an error in Visual Studio after applying the Service Pack (it's for client PC's - report designers - as well as for the SQL Server/web server) which read:

Could not load type Microsoft.ReportingServices.Interfaces.CachedDataStatus 

The solution was at http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&frame=right&th=b1ccf47d2cd15078&seekm=epuanhTWEHA.2544%40TK2MSFTNGP10.phx.gbl#link7, which said:

Just out of curiosity, would you do a search under the hidden folder:

C:\Documents and Settings\\Local Settings\Application Data\assembly\dl2

for a file named

Microsoft.ReportingServices.Interfaces.*

If it's there, rename it and see if that resolves the issue.  If it does, you may delete the file.
Overall a fairly painless experience, which has improved the functionality of an already pretty good application.

Reporting Services SP1

As promised by Microsoft, covered by many many others, and incidently delivered right on time, Reporting Services Service Pack 1 is now available.

I'm getting ready to load it up over the next couple of days. The big thing we've been waiting on is better Excel support (for versions prior to 2002) and grouping in Excel (which was in the beta, but pulled for the final product).

The main gripe I'm hearing from my users is not being able to print directly from Internet Explorer. I believe it's got something to do with IFRAMEs, and the workaround I'm offering is to export to PDF and print it there.

Re-indexing Tables with Original Fillfactor

As part of a weekly database job that runs out-of-hours, I re-index all the tables in a particular reporting database. After playing around with index fillfactor I arrived at a fill factor of 90 as the tables are mostly being read and only being updated a couple of times a month. For my key tables, I made sure I set up clustered indexes on the fields that were being used most commonly in my queries (which of course speeds data access up considerably)

I discovered a simple script that would rebuild indexes on all tables in a database to have a fill factor of 90 (see http://www.sql-server-performance.com/rebuilding_indexes.asp), but I wanted more customisation so wrote a script to rebuild all indexes with their original fill factor (some of may tables are set higher as the table is never updated, and some are set lower as the table is updated more often).

So, here's the script, which doesn't actually do the re-indexing, just PRINTs the relevant statements to the Messages window (if using Query Analyzer):

  --table name variable
  DECLARE @TableName VARCHAR(255)
  --index name variable
  DECLARE @IndexName VARCHAR(255)
  --original fill afctor variable
  DECLARE @OriginalFillFactor TINYINT
  --override fill factor (can be NULL)
  DECLARE @OverrideFillFactor TINYINT
  --set override fill factor for indexes here, if required. This WILL overwrite the original value
  --for each index! (If commented out, original fill factor will be used)
  --SET @OverrideFillFactor = 90

  --temporary table for holding all indexes
  CREATE TABLE #tempIndexes 
  (
      index_name VARCHAR(255), 
      index_description VARCHAR(210), 
      index_keys NVARCHAR(2048)
  )
  --temporary table for holding table name, index name, index id and fillfactor
  DECLARE @temp TABLE (
      TableName VARCHAR(255), 
      IndexName VARCHAR(255), 
      IndexId INT, 
      OriginalFillFactor TINYINT
  )

  --set NOCOUNT ON
  SET NOCOUNT ON

  --get all the tables using INFORMATION_SCHEMA.TABLES into a cursor
  DECLARE TableCursor CURSOR FOR
  SELECT  TABLE_NAME 
  FROM    INFORMATION_SCHEMA.TABLES 
  WHERE   TABLE_TYPE = 'BASE TABLE'

  --open the cursor
  OPEN TableCursor
  --get the first row
  FETCH NEXT FROM TableCursor INTO @TableName
  --if we got a valid row, continue
  WHILE @@FETCH_STATUS = 0 BEGIN 
      --clear out the #temp table, containing indexes for the passed table
      DELETE FROM #tempIndexes
      --get indexes into #tempIndexes. This may print a warning message "The object does not 
      --have any indexes.", which can be ignored
      INSERT INTO #tempIndexes EXEC sp_helpindex @TableName

      --insert into outer table, the table name, the index name
      INSERT INTO @temp ([TableName], [IndexName])
      SELECT  @TableName, index_name
      FROM    #tempIndexes

      FETCH NEXT FROM TableCursor INTO @TableName
  END

  CLOSE TableCursor
  DEALLOCATE TableCursor

  --drop the temp index table
  DROP TABLE #tempIndexes

  --now get the index id and original fill factors
  UPDATE  @temp
  SET     IndexId = i.[indid], OriginalFillFactor = i.[OrigFillFactor]
  FROM    sysindexes i, sysobjects o, @temp T
  WHERE   i.[id] = o.[id] AND o.[name] = T.TableName AND T.IndexName = i.[name]

  --lastly loop through the @temp table and re-index
  DECLARE DBREINDEXCursor CURSOR FOR
  SELECT  TableName, IndexName, OriginalFillFactor 
  FROM    @temp
  --open cursor
  OPEN DBREINDEXCursor
  --get first row into local variables
  FETCH NEXT 
  FROM    DBREINDEXCursor 
  INTO    @TableName, @IndexName, @OriginalFillFactor
  --loop through cursor while there are rows remaining
  WHILE @@FETCH_STATUS = 0
  BEGIN
      --if we've been given an override fill factor, apply it here
      IF NOT (@OverrideFillFactor IS NULL) SET @OriginalFillFactor = @OverrideFillFactor 
      --do the re-index operation here
      PRINT 'DBCC DBREINDEX(' + @TableName + ',' + @IndexName + 
          ',' + CONVERT(VARCHAR(3), @OriginalFillFactor) + ')'
      --get the next row
      FETCH NEXT 
      FROM    DBREINDEXCursor 
      INTO    @TableName, @IndexName, @OriginalFillFactor
  END

  --close and deallocate the cursor
  CLOSE DBREINDEXCursor
  DEALLOCATE DBREINDEXCursor

  GO

Some indexing resources I found helpful are at http://www.c-sharpcorner.com/Code/2004/March/SQLPerformanceChecklist06.asp, http://www.extremeexperts.com/sql/articles/BestPractices.aspx and http://www.sql-server-performance.com/rebuilding_indexes.asp.

 

June 2004 Melbourne SQL Server SIG - Replication Lessons from the Real World

Here's my brief overview of Tuesday's Melbourne SQL Server SIG on "Replication Lessons from the Real World", presented by Adam Thurgar at Microsoft Melbourne Offices on Chapel Street:

Adam did a great job presenting the topic (which I have absolutely zero prior experience with), and quickly established his credibility by talking about the work he does with Match.com and it's 90GB database (leaves my largest, at 2GB, looking pretty pathetic). Adam spoke candidly about problems he'd encountered and alluded to several improvements in Yukon, all the while infusing his talk with humour and trying to keep the audience involved. His presentation was mostly theory (no code, no screenshots, no demos) but he was quick to take questions from the group gathered.

The highlight of the talk for me was when he covered three or four "don't do this at home" scenarios where he was able to work around some of the limitations/correct replication mistakes using the SQL Server System Tables. I went along with a particular business need in mind, and so was able to extract enough information to make a decision (my decision was yes, we'll use replication, but I need to do some more research first). I'm looking forward to reviewing the PowerPoint slides Adam used, when they get posted (at the Australian SQL Server User Group site).

There were fewer attendees than the last time when Reporting Services was being discussed, which is no problems because bigger doesn't necessarily mean better. Myself, I struggle with large crowds and have absolutely zero networking skills. Maybe it's time to learn some!

Overall I enjoyed the night from a technical side, and I'm looking forward to the future SIG's which will be targeted at Yukon.

Upcoming June 2004 Melbourne SQL Server SIG - Replication Lessons from the Real World

Tonight is the Melbourne SQL Server SIG on replication, presented by Adam Thurgar. Replication is not something I know a great deal about - I'm hoping to learn ways to sync our production and development servers as currently I use multiple DTS jobs coded by hand and scheduled with SQL Server Agent. The DTS/SQL Agent approach is very flexible, but I want simple: whenever a new table is added, data is synchronised, and the two servers are kept exactly the same.

Hopefully replication is the answer! I've printed an article from DatabaseJournal called Setting Up Merge Replication: A Step-by-step Guide to read while I'm waiting around beforehand, to at least open my eyes to what can be done.

Anyway I should have more to report on in the coming days.

Finding Stored Procedure/Table Dependencies

Recently I had a problem that I needed to update my stored procedures to point at a new set of tables. I systematically worked through my 3 stored procedures for populating the tables, but I couldn't remember all the stored procedures that accessed them for data retrieval.

Enter information_schema.routines and a tip from Experts Exchange:

select * from information_schema.routines where routine_definition like '%yourtablename%'

The downside is that this searches the stored procedure text (well, the first 4000 characters in the routine_definition column) for the table name, so you'll get hits even where the table name is used in a comment. The upside is that dynamic SQL is accounted for.

MS Application Updater Block

From Brendan, a great step-by-step post on the MS Application Updater block, which I had downloaded months ago and have sitting around for when my app gets closer to deployment (in a month or so).

I also use the Data Access Application Block (V2, currently, as SQL Server support is all I need). I passed over the error logging Application Block in favor of log4net which more than meets the requirements I've got.

Ohad's Reporting Services Links

Ohad has a list of Reporting Services links that look interesting.

GUIs Part 2

While I'm thinking of GUIs, the GUI Olympics (which has to do with skins, rather than full-blown widgets and interfaces) produced some nice looking interfaces. When I ran Mandrake at home I was pleased with the amount of customisation that could be done, being the tweaker that I am.

GUI Design Guidelines

It's a little out-of-date, but the Isys Information Architectssite has a whole lot of examples of good (Hall of Fame) and bad (Hall of Shame) GUIs, dialog boxes and "features" (from I don't know where).

SQL Server Developer Centre

Via Early Adopter comes new of an Microsoft SQL Server Developer Centre with the standard articles, downloads and KB's, but also links to blogs and an RSS feed.

Me, Me, Me

Obligatory first post - my name is Thomas Williams, I'm a Melbourne, Australia-based senior systems analyst working mainly with SQL Server (and Analysis Services, Reporting Services) and VB.NET. I'm 30 years old, and I'm looking forward to sharing what I've got with anyone who might be interested!

I've been reading blogs for a year or so now, and writing my own personal blog at http://thomasswilliams.blogspot.com/ since September 2004.

May 2004 Melbourne SQL Server SIG - Reporting Services Deployment

My musings on the May SQL Server SIG in Melbourne, Australia (a few days late)...

The Rundown
I went to a Special Interest Group meeting at Microsoft in Melbourne a couple of weeks back. I had seen the presenter, Jason Buck, before and once again he demonstrated how well he knew the product (assisted by David from MS and Greg, a consultant tasked with "..extracting out of the community...expertise..."). There were lots of people there (more than I'd seen at an SQL Server SIG before), which is a good indicator of the poularity of this add-on to SQL Server 2000 - I know it's hard to tell a book by it's cover (or a man by his clothes), but looking at the range of people and judging by the suits, there were some BI-type people, some developers, some managers.


The Highlights
Jason focused on deployment and backup. He kind of powered his way through the slides, and part of the reason for that was the side discussions that kept coming up based on questions from the audience. I was hoping to see more "tips and tricks" relating to advanced report design as our deployment here was fairly painless - I guess I'll wait for the "Hitchhiker's Guide to SQL Server 2000 Reporting Services" book (see
http://www.sqlreportingservices.net). One 'wow' factor was a command-line tool to build folders, set permissions and deploy reports called "rs.exe" which used special ".rss" batch files written in VB.NET. Very cool.

The other highlight was the amount of feedback the team running the night asked for, in terms of future topics with the SIG and the desire to build a community. I see this commonly online, but in person I find it's even more rewarding. Looking forward to the next SIG in June (see http://www.local.microsoft.com.au/australia/events/register/home.aspx?levent=268429 for details).