Blog Home  Home RSS 2.0 Atom 1.0 CDF  
Mark Mrachek - Business Intelligence Blog - Wednesday, April 19, 2006
 
 Wednesday, April 19, 2006

Recently, I was setting up drillthrough on a degenerate dimension with ROLAP storage.  I encountered the error below when executing the drillthrough action.

 

 

Using SQL Server profiler, I was able to locate the cause of the issue.  Looking at the trace, I noticed that the ‘IntegerData’ trace field was failing at row 310,000 so I looked at server properties to see which ROLAP related properties were set to 300,000. 

 

The culprit turned out to be ‘ROLAPDimensionProcessingEffort’ which was set to 300,000.  So, as a test, I set the property to 2,000,000 (a number higher than the number of members in my degenerate dimension) and this resolved the error. 

 

Although changing this property resolved the error, the cost of using the ROLAP storage for this dimension turned out to be quite expensive.  My greatest concern was that a huge number of dimension members were being queried and cached when I was essentially targeting only 30 records for drillthrough. 

 

I had posted this problem to an internal message board at Microsoft and was informed that “…client applications may mistakenly try to fetch more data than they really wanted to from ROLAP dimensions…”.  This is why the ‘ROLAPDimensionProcessingEffort’ property exists.  

 

Needless to say, I’m not impressed with ROLAP dimensions and this one more reason to avoid using them if you can.

 

 

4/19/2006 7:51:11 AM (Pacific Daylight Time, UTC-07:00)  #    Comments [0]   Analysis Services  | 
 Saturday, April 15, 2006

In case you haven't heard yet, Microsoft recently purchased ProClarity.  Here is a link to the press release.

4/15/2006 1:25:26 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [0]   Web Reporting  | 
 Saturday, February 25, 2006

I've been working with a new User Interface Platform group in Microsoft Services IT for the last three months.  This group is using Panorama as their BI interface within their platform. 

Although I have a bias toward building custom web based applications for BI UI's, I must say that I'm impressed with Panorama.  The charting is great and the security models are flexible.  I would say the biggest drawback I've seen at this point is that Panorama does not handle dynamic security models in Analysis Services very well.

One thing I really like about Panorama is that you can customize slicer security by altering their base asp files which gives you maximum flexibility when dealing with data level security.

I'll try to post more information about Panorama in the future.

2/25/2006 12:02:35 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]   Web Reporting  | 
 Sunday, February 19, 2006

If you have ever used the NonEmptyCrossjoin function, you may have been surprised (and frustrated) with the results your queries returned.  This function was added to Analysis Services 2000 to help with performance of queries, but it commonly returned incorrect results.  Fortunately the NonEmptyCrossjoin function is being deprecated.

 

The NonEmpty() function is new in Analysis Services 2005 and should be used instead of the NonEmptyCrossjoin function.  The NonEmpty() function is powerful because it can be applied to MDX expressions whereas the NON EMPTY clause was only available at the top level in SELECT statements.

 

This syntax for the NonEmpty() function is NonEmpty({set},[filter set])

 

I met with a developer and PM from the Analysis Services team last week in Redmond and they provided me with more information on the NonEmpty() function. 

 

If you use the NonEmpty() function without a filterset, then the expression is evaluated using the default measure in your cube.  So, if you do not define a filterset and you did not specify a default measure in your cube, then you may get unexpected results with this function.  Because, even though you may not have explicity defined a default measure, all cubes have a default measure (Analysis Services will define a default measure even if you did not define one) and the NonEmpty() function will use this default measure as the context in which to evaluate the expression.

2/19/2006 6:21:11 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]   MDX  | 
 Tuesday, February 14, 2006

I have been developing reporting systems for over nine years.  For the last six years I’ve been working as an independent contractor and consultant for my own company, dymetrics, inc., which specializes in delivering Business Intelligence solutions.

 

In November of 2005, I joined a consulting company as a full-time employee to work on a contract at Microsoft. 

 

Although my areas of expertise include data warehousing, OLAP, and ASP.Net development, my primary focus at Microsoft has been working with Analysis Services 2005.  I have also been helping the new User Interface Platform group in Microsoft’s Services IT department implement Panorama as their Business Intelligence user interface.

 

Once my assignment is completed at Microsoft, I will most likely go back to independent contracting since I prefer working independently as opposed to being a full-time employee.

2/14/2006 1:05:40 AM (Pacific Standard Time, UTC-08:00)  #    Comments [0]   Consulting  | 
 Saturday, February 11, 2006

I’ve found myself working with UDF’s more and more lately and thought it would make a good blog topic. So, if you are interested in creating a UDF to use in your MDX, read on.

 

I’m using the Adventure Works database which is the sample database Analysis Services 2005.  If you have not yet created the Adventure Works database, you can get the source files and installation instructions here.

 

First, create a class library in Visual Studio.

 

Here is a very basic sample of a C# class library I created:

using System;
using System.Collections.Generic;
using System.Text;

namespace AWLib
{
public class Utilities
{
public string GetSomeSet(){
int sec = DateTime.Now.TimeOfDay.Milliseconds;
string set;

if (sec < 200) {
set = "[Date].[Fiscal].Children";
}
else if (sec < 400)
{
set = "[Reseller].[Reseller Type].Children";
}
else if (sec < 600)
{
set = "[Employee].[Employees].Children";
}
else if (sec < 800)
{
set = "[Geography].[Geography].Children";
}
else {
set = "[Sales Channel].[Sales Channel].Children";
}
return set;
}

}
}

Next, after you have successfully compiled your class library, you need to add it to the Adventure Works database.  You do this by:

1)      Opening SQL Server Management Studio

2)      Right click on the ‘Assemblies’ folder in the Adventure Works database, then click on ‘New Assembly…’

 

Note: You can also add your class library to the server assemblies so the UDF’s will be available in all databases on your Analysis Services instance.  Also, you can add your assembly to your ‘Business Intelligence Development Studio’ project and deploy your assembly along with your database.

 

To test the UDF (from above), open a ‘New Query’ window in SQL Server Management Studio, select the Adventure Works database and execute the following MDX.

 

SELECT Measures.Members ON 0,
STRTOSET(AWLib.GetSomeSet()) ON 1
FROM [Adventure Works]

The AWLib.GetSomeSet() function will return different sets based on the milliseconds from the timestamp on your server. 

 

UDF’s are very powerful and flexible and help to extend the functionality of MDX.  Here are just a few examples of how you can use UDF’s 1) implementing dynamic security in Analysis Services, 2) dynamically building sets and tuples, and 3) creating complex mathematical calculations.


2/11/2006 12:51:43 AM (Pacific Standard Time, UTC-08:00)  #    Comments [0]   Analysis Services  | 
 Saturday, February 04, 2006

I ran into this error the other day when attempting to design aggregations for a cube using the AS 2005 Aggregation Design Wizard.  The full error was: "Clr Assembly must have main file specified. To restart the process, resolve the problem and then click Start."

I was able to able to resolve this error by:   
    1) Stopping the services of AS where your database resides
    2) Renaming the data directory for Analysis Services Databases.
        Default location: C:\Program Files\Microsoft SQL Server\MSSQL.2\OLAP\Data  (rename the 'Data' folder to 'Data_OLD')
        Note: MSSQL.2 is the location for the AS files on *my* server.  You're AS folder may be named MSSQL.1 or MSSQL.3 or whatever.
                Also note, when you rename this folder, all existing databases that resided in your instance of AS are now unavailable.  You will need to re-deploy all of your databases to this server (if applicable).
    3) Create a new folder in the 'C:\Program Files\Microsoft SQL Server\MSSQL.2\OLAP\' directory called 'Data' (basically replacing the original 'Data' folder you renamed in Step 2 with a new "empty" folder)
    4) Start the AS Services on your server
    5) Deploy your Analysis Services Project to the server
    6) Create your aggregations.

This error has nothing to do with your database objects but everything to do with internal AS files.  Why or how this occurs is beyond me, but some AS files must be corrupt which causes this error.
2/4/2006 11:30:08 AM (Pacific Standard Time, UTC-08:00)  #    Comments [0]   Analysis Services  | 
 Wednesday, January 25, 2006

I’ve written thousands of lines of MDX code over the years to support web reporting applications and today I discovered something new.  Although it probably isn’t new to MDX, it was new to me because I never needed it until today.  I was targeting the ascendants of a member and based on the parent of the member, I needed to alter the slice of the cube.

Typically, when I use conditional statements, I create calculated member and handle the logic in the WITH statement.  Today’s challenge was different because I was not able to control what calculated members are passed from Panorama to Analysis Services.  Instead, I needed to work through the ‘WHERE’ clause to slice my data.  

Anyways, I don’t know if I’ll ever need to use it in the future, but it’s nice to know that this functionality exists.  Below is a sample MDX statement that uses a conditional statement in the ‘WHERE’ clause.  This sample provides little value except to illustrate that you can indeed use conditional statements in ‘WHERE’ clauses.

SELECT [Measures].[Internet Total Product Cost] ON 0,
[Sales Reason].[Sales Reasons].Members ON 1
FROM [Adventure Works]
WHERE (IIF([Sales Territory].[Sales Territory].[Sales Territory Country].[Australia].Parent.Name = “Pacific”, [Sales Territory].[Sales Territory], [Sales Territory].[Sales Territory].[Sales Territory Country].[Australia]))

1/25/2006 10:46:50 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]   Analysis Services | MDX  | 
Copyright © 2010 Mark Mrachek. All rights reserved.
DasBlog 'Portal' theme by Johnny Hughes.