Overblog Folge diesem Blog
Edit post Administration Create my blog
Blog von Olaf Helper

SSAS Objekte per AMO verarbeiten und Verlauf per SessionTrace verfolgen

18. Februar 2011 , Geschrieben von Olaf Helper Veröffentlicht in #OLAP

Einen Microsoft Sql Server Analysis Services (SSAS) Cube und dessen Objekte lässt man im produktiven Betrieb natürlich zeitgesteuert per SSIS Package verarbeiten; da will man nicht wirklich bei „zusehen“.

Während der Entwicklungs- & Designphase eines Cube’s lässt man diesen aus BIDS heraus verarbeiten. Die Daten basieren dabei meist auf Views, die die eigentlichen Daten auf eine repräsentative als auch vertretbare Datenmenge beschränken; schließlich verarbeitet man öfter mal den Cube, um das Ergebnis zu kontrollieren und das soll ja nicht jedes Mal einen halben Arbeitstag in Anspruch nehmen. Der Processing Verlauf wird dabei in BIDS (und auch SSMS) in einem TreeView dargestellt und das bietet einem nicht gerade eine gute und informative Darstellung des Verlaufes.

Andererseits sind die Verlaufsinformationen (mir) wichtig, um von den Test- auf die Produktionsdaten hochrechnen zu können.

AMO bietet die Möglichkeit mit einem .NET Programm oder PowerShell programmatisch einzelne Objekte eines Cubes verarbeiten zu können. Über einen Trace könnte man alle Aktivitäten auf dem Analysis Server nach verfolgen und die der eigenen Session herausfiltern; nicht so ganz einfach. Es geht aber auch wesentlich einfacher, indem man das SessionTrace des AMO Server Objektes verwendet, über das man auch die Verarbeitung der Objekte durchführt. Man setzt eine Variable WithEvents, startet den Trace und kann dann alle Ereignisse Event-gesteuert empfangen. In TraceEventArgs erhält man alle Daten, so wie man sie auch aus dem SQL Profiler kennt.

Es gibt aber kleine Probleme mit ein paar Properties von TraceEventArgs, die könnten durch „Ungenauigkeit“ (alias Bug) in AMO verursacht werden und die gilt es zu umschiffen. Das betrifft zum Beispiel das Property IntegerData. Natürlich und verständlicherweise gibt es nicht bei jedem TraceEvent einen Wert für IntegerData, aber dann würde ich davon ausgehen, das entweder Nothing (C# null) oder -1 geliefert wird. Stattdessen erhält man den Laufzeitfehler

 

 System.ArgumentNullException: Der Wert darf nicht NULL sein. Parametername: String 
  bei System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal) 
  bei System.Number.ParseInt64(String value, NumberStyles options, NumberFormatInfo numfmt) 
  bei Microsoft.AnalysisServices.TraceEventArgs.get_IntegerData() 

 

egal was man macht; eine einfach Prüfung auf IsNothing reicht bereits als Auslöser. Nun könnte man aufwendig auf alle EventClass / EventSubClass Kombinationen filtern, wo zugesichert ein Wert vorkommt. Ich mache es mir einfacher und deswegen kapsele ich die Abfrage des IntegerData, das bei manchen Events den Fortschritt bzw. die Anzahl verarbeiteter Datensätze enthält, in einer eigenen Funktion und fange den Fehler mit Try Catch ab. Betroffen sind von dem Phänomen die Properties CpuTime, Duration, IntegerData, ProgressTotal, Serverty.

 

Der Rest ist einfach, ich lasse die TraceEventArg-Daten in einer Console ausgeben, der VB.Net Code dazu sieht so aus:

 

 

Imports Microsoft.AnalysisServices
 
Module DimProcess
 
    Private WithEvents mSessionTrace As SessionTrace
 
    Sub Main()
        Dim server As New Server
        server.Connect("MeinServer\MeineInstanz")
 
        Dim database As Database = server.Databases("Adventure Works Cube")
        Dim dimension As Dimension = database.Dimensions("Dim Customer")
 
        mSessionTrace = server.SessionTrace
        mSessionTrace.Start()
 
        Console.WriteLine ("{0} Start of processing"Date.Now().ToString("T"))
        dimension.Process(ProcessType.ProcessFull)
 
        mSessionTrace.Stop
        mSessionTrace = Nothing
        Console.WriteLine ("{0} End of processing"Date.Now().ToString("T"))
        
        dimension.Dispose
        database.Dispose
        server.Disconnect
        server.Dispose
 
        Console.WriteLine ("Hit any key")
        Console.ReadKey
    End Sub
 
    Private Sub mSessionTrace_OnEvent(ByVal sender As ObjectByVal e As Microsoft.AnalysisServices.TraceEventArgs) _
        Handles mSessionTrace.OnEvent
        
        Select Case e.EventSubclass            
            ' Uninteressante EventSubClass:
            Case  TraceEventSubclass.Subscribe, TraceEventSubclass.SqlQuery, _
                  TraceEventSubclass.DiscoverXmlMetadata, TraceEventSubclass.ExecuteSql
            Case Else
                If Not String.IsNullOrEmpty(e.TextData) AndAlso not e.TextData.StartsWith("<"then
                    Console.WriteLine ("{0} {1} {2}"Date.Now().ToString("T"), GetIntegerdata(e), e.TextData)
                end if
        End Select
        
    End Sub
 
    Private Function GetIntegerdata(ByVal e As TraceEventArgsAs string
 
        Try
            Dim result As long = e.IntegerData
            Return result.ToString().PadLeft(6)
 
        Catch ex As Exception
            Return String.Empty.PadLeft(6)
        End Try
 
    End Function
 
End Module

 

Zugegeben, mit dem AdventureWork Demo gibt es nicht groß Daten zu verarbeiten, deswegen ist die Ausgabe auch nicht gerade spektakulär:

 

ProcessCubeObject.jpg

Diesen Post teilen

Repost 0

Kommentiere diesen Post