Articles Tagués ‘Analysis Services’

Proratisation des objectifs dans le temps dans Analysis Services : utilisation de SCOPE

12 mars 2011

Rappel sur la notion d’objectifs

Quand on crée des KPI, on a besoin de travailler les objectifs des indicateurs.

On peut écrire les objectifs en dur dans les KPI (dans Analysis Services via Visual Studio ou dans un outil plus adapté comme le Dashboard Designer de Performance Point). Mais bien évidemment, ce n’est pas la “bonne pratique” recommandée.

La première étape est de créer une table d’objectifs. Vu du cube, c’est une simple table de faits, ventilée sur les dimensions adéquates. Cependant, il est rare que les objectifs soient connus (et encore moins saisis) à une granularité très fine.

Problématique

Prenons l’exemple d’une mesure chiffre d’affaire. En phase de planning budgétaire, on va déterminer les objectifs de CA par mois par exemple. Il y a rarement de linéarité sur cette mesure mais il est rare qu’on descende à la journée. Smile

Admettons qu’on veuille avoir un indicateur au jour le jour car on intègre des factures quotidennement. On va avoir un problème sur notre KPI car en début de mois, nous serons loin de l’objectif et nous ne pourrons savoir si on est “dans les clous” qu’une fois le mois quasiment terminé car le seul chiffre que l’on ait est celui du mois. Difficile de piloter de cette façon.

Solution(s)

L’idée est donc de proratiser notre objectif sur la dimension temps pour obtenir l’objectif sur la granularité voulue (dans notre exemple la jour). Je vous propose donc 3 solutions dans cet article :

Remplir la table de faits à la bonne granularité

La première solution est la plus simple car il suffit de remplir directement notre table d’objectifs à la bonne granularité et donc avoir un objectif quotidien.

Le problème de cette solution est qu’il faut modifier beaucoup de lignes si je devais revoir l’objectif d’un mois par exemple. Nous avons donc un problème de praticité même si évidemment, on ne remplit la table qu’une fois et on la modifie rarement.

Ventiler les objectifs dans le DSV

Le modèle d’Analysis Services permet d’avoir une abstraction sur le DatawareHouse via le DSV (Data Source View). Cette abstraction permet d’interférer sur le modèle de données via du code T-SQL.

La seconde solution utilise cette possibilité pour changer la granularité de la table d’origine. En T-SQL, on démultiplie les lignes afin d’en obtenir une par jour et on divise l’objectif selon le nombre de jours. Je vous passe le script car je ne souhaite pas focaliser sur cette méthode.

Ventiler les objectifs dans le cube

La troisième solution est d’opérer la ventilation non pas en T-SQL mais dans le cube, en MDX.

Pour cela, il suffit tout simplement de surcharger le calcul des cellules du cube et le langage MDX nous permet de le faire simplement. On utilise l’instruction SCOPE et on redéfinit le contenu de la cellule. Cela se fait dans l’onglet Calculations d’un cube dans Visual Studio.

Scope
  ( { [Temps].[Calendrier].[Date] }, { [Measures].[Budget] } );

This =
  ([Temps].[Calendrier].Parent)
  /
  [Temps].[Calendrier].CurrentMember.Siblings.Count;

End Scope;

La première partie du script définit la portée du calcul. Jusqu’à l’instruction End Scope, on est donc borné à la mesure Budget au niveau Date, plus rien d’autre n’existe.

This= redéfinit les cellules de la portée avec un nouveau calcul. Ici, je prends le tuple parent (donc le budget du niveau mois, qui, lui, est défini) et je le divise par le nombre de dates en dessous (ie. le nombre de jours dans le mois).

J’obtiens donc une proratisation du budget mensuel par jour.

A noter qu’avec le scope, je ne perturbe pas le niveau mois car ce script passe après le calcul initial des cellules (CALCULATIONPASS, mais ça c’est une autre histoire Smile with tongue out).

Conclusion

Je n’ai pas de préférence pour l’une ou l’autre de ses méthodes. La plus technique est sans aucun celle en MDX. Toutefois, utiliser un script T-SQL dans le DSV est pragmatique car on s’appuie ensuite sur la simplicité de l’aggrégation du cube.

D’un point de vue performances, je n’ai jamais fait de tests. Je le mets dans ma TODO-List et ce sera l’occasion d’un nouvel article.

Format Currency pour un membre calculé

26 février 2011

Je reviens sur un post qui date de plus de 2 ans : http://blog.djeepy1.net/2008/08/31/analysis-services-support-du-format-monetaire-dans-excel/

J’expliquais la gestion du formattage d’une mesure dans Analysis Services. J’ai été très précis la dernière fois et pour ce rapel, je vais juste faire un petit reminder sous la forme d’une FAQ.

Q : J’ai un membre calculé dont j’ai précisé le format à Currency et pourtant, il apparaît comme un simple nombre dans Excel, que dois-je faire ?

R : Pour un membre calculé, il faut préciser le langage en plus du format 
FORMAT_STRING = "Currency", LANGUAGE = 1036,

Time Intelligence

20 janvier 2011

Un petit post sur le wizard de “Business Intelligence” de BIDS. Avec cet assistant, il est possible de créer des membres calculés ajoutant des fonctionnalités dans un cube.

Dans les fonctionnalités régulièrement rencontrées, il y a tout ce qui touche à l’agrégation dans le temps ; par exemple, on peut citer les classiques YTD (Year-to-Date) ou YoY (Year-over-Year), etc.

Le wizard permet de créer automatiquement ces mesures dans la rubrique Time Intelligence

image

Seulement, il est important de savoir comment BIDS crée ces membres car elle est un peu atypique – ie. on (et j’en fais partie) peut créer différemment ces mesures.

Voici comment l’assistant procède :

  • Il crée un nouvel attribut dans la dimension Temps. Cet attribut va contenir les différents calculs (YoY, YTD, etc.)
  • Il crée par script les membres « virtuels » de cet attribut
  • Il crée le script MDX avec les calculs via une instruction SCOPE

clip_image001

Cette façon de faire (l’utilisation de l’instruction SCOPE) permet de réduire les calculs à un slice uniquement (le membre ‘”virtuel” de la dimension temps). Cela optimise le cube mais ajoute une complexité dans sa définition (et donc une maintenabilité plus difficile).
Attention, le calcul est figé au moment de l’exécution du Wizard et donc des modifications du cube peuvent nécessiter une correction du script MDX généré.

L’avantage de cette solution est aussi dans l’utilisabilité qu’elle offre à l’utilisateur. En effet, si vous avez déjà beaucoup de mesures (même bien organisées dans les DisplayFolder), l’ajout des mesures calculées peut vite devenir ingérable. Cette façon de faire permet de déporter toutes ces mesures dans une dimension, offrant une matrice calculs/mesures.

Dimension Scenario

19 décembre 2010

image

 

Je rencontre fréquemment en consulting des problématiques relatives aux budgets et/ou aux prévisionnels à intégrer dans un cube.

Comme souvent en décisionnel, il y a de nombreuses façons de traiter (concevoir) ce type de fonctionnalité et le but de ce post n’est en aucun cas de rédiger un état de l’art sur le sujet.

Je propose en règle générale 2 approches :

  • utilisation d’une table de budgets
  • utilisation d’une dimension scénario

Je vais passer vite sur la première approche puisqu’elle consiste à ajouter des mesures représentant les budgets. Bien souvent, on a un table de faits dédiée (et donc un groupe de mesure). On peut donc jouer avec les mesures Ventes et Ventes prévues par exemple.

J’aime cette approche car elle permet d’avoir une granularité différente de la table de faits principale (qu’on résout par des Cube Calculation mais c’est une autre histoire Smile).

La dimension Scenario

L’idée de cette approche consiste à créer une nouvelle dimension qui contient les scénarios de travail comme par exemple Courant (Actual), Budget 1, Budget 2, Prévisionnel (Forecast), etc.

On ajoute donc une clé dans la table de fait pour le scénario pour gérer la nouvelle dimension. Cela permet d’avoir une infinité de scénarii, utile en période de planification budgétaire (d’ailleurs les utilisateur de feu Planning Server connaissent très bien cette approche).

Scenarii

C’est cette technique qui est utilisée dans la réalisation de cubes comptable.

Evidemment, on utilisera un Default Member sur cette dimension afin de ne pas perturber l’usage en affichant naturellement le scénario courant.

Remplissage d’une dimension temps

19 décembre 2010

Pour générer et alimenter automatiquement une table de dimension temps, il  existe une option dans l’assistant de création des dimensions de BIDS.

Créez une nouvelle dimension en suivant les étapes suivantes :

Assistant dimension temps - step 1
Choix de la bonne option

Assistant dimension temps - step 2
Choix de la plage de dates

Assistant dimension temps - step 3

Assistant dimension temps - step 4
Démarrage de l’assistant de génération de la table dans le DataWarehouse

Assistant dimension temps - step 5
Ne pas oublier de choisir l’option Populate pour générer les enregistrements

A ce stade, la table est générée et alimentée.

Pour anticiper le passage en production, je mets un profiler sur ma base de développement pour récupérer le script de remplissage (populate).

Je refais la même manipulation pour mettre à jour la dimension temps. En effet, on ne mets pas toujours toutes les dates possibles dans la dimension et je prends l’habitude de mettre un reminder fin novembre pour alimenter l’année qui arrive. (voire faire un script qui la génère automatiquement).

 

PS : merci Philippe de l’équipe DGD de Bewise pour les screenshots.

Mot reservé qui manque à la liste en MDX

10 octobre 2010

Lors du développement d’un script MDX, je ne comprenais pas pourquoi j’avais une erreur au parsing.

Voici le script (un condensé, évidemment) :


WITH MEMBER firstdate AS 0SELECT {firstdate} ON 0 FROM [Adventure Works]

Executing the query ...Query (1, 13) Analyseur : La syntaxe pour 'firstdate' est incorrecte.

Quel est le problème avec ce script ? Eh bien c’est tout simplement que mon script contient un mot clé réservé. Vous l’aurez deviné, ce mot-clé est firstdate.

Pourtant si on regarde dans la liste qui se trouve dans la MSDN (http://msdn.microsoft.com/en-us/library/ms145629.aspx), aucune trace de FIRSTDATE.

Pour se convaincre que le problème vient bien du nom du membre calculé, il suffit de changer le script pour qu’il fonctionne.


WITH MEMBER firstdate2 AS 0SELECT {firstdate2} ON 0 FROM [Adventure Works]

Conclusion : attention aux noms de variable mais pour faire plus simple, utiliser les [] pour indiquer au parser que c’est un identifiant.

Tuning des attributs de dimension dans Analysis Services

21 mai 2010

 

Les attributs d’une dimension dans un cube servent à la base à analyser les données selon les valeurs qu’ils contiennent. Par exemple, dans une dimension produit, on peut avoir des attributs comme la couleur, le poids, la gamme, le nom du designer qui l’a créé, etc.

Dans la vraie vie, une dimension peut contenir un grand nombre d’attributs. Le problème est que souvent, certains attributs n’ont rien à voir avec de l’analyse. Par exemple, un attribut Adresse dans une dimension client n’est pas un bon candidat pour l’analyse (et je parle bien de l’adresse du genre “3 rue des macarons cuits”, pas de la ville ou du code postal).

image

Néanmoins, on trouve souvent ce genre d’attributs à des fins de présentation dans un rapport (pour du publipostage ou de l’export par exemple).

Mon premier avis serait d’orienter ce genre de restitution de données vers une base de production (ou tout du moins dans une base relationnelle) comme source de données et non un cube mais ce n’est pas toujours possible.

L’approche que j’utilise est la suivante. Je catégorise avec mon client les attributs :

  • Attribut d’analyse : utilisé pour ventiler les mesures
  • Attribut intermédiaire : attribut technique utilisé dans une Referenced Dimension Usage par exemple
  • Propriété simple : utilisé pour afficher des méta-données sur le client

En fonction de ma classification, je configure les attributs différemment pour optimiser mon cube :

image

Enabled

Visible

OptimizedState

Attribut d’analyse

True

True

FullyOptimized

Attribut intermédiaire

True

False

NotOptimized

Propriété

False

N/A

NotOptimized

Il y a toutefois encore un problème à résoudre. En effet, le fait de mettre AttributeHierarchyEnabled à false, empêche de voir la propriété dans les assistants d’un outil comme Report Builder.

En effet, en requêtage MDX, on récupère un CellSet qui peut contenir, si on les demande dans la requête, les méta-données mais il faut que le client OLAP sache les exploiter correctement.

Par exemple, Excel (2007+) sait les demander et les afficher nativement.

image

Dans Report Builder, on devra passer par un membre calculé pour remonter la propriété comme une mesure avec une expression comme celle-ci.

[Tiers].CurrentMember.Properties(“Adresse”)

La méthode est décrite dans ce post :
 http://blog.djeepy1.net/2009/01/27/report-builder-2-0-creer-un-membre-calcule-sans-passer-par-ssas/

Obtenir les métadonnées d’un cube via PowerShell

13 mai 2010

Cas pratique : obtenir la liste des attributs des dimensions leurs caractéristiques et leurs croisements avec les groupes de mesures (sous format exploitable type Excel évidemment).

Une solution pragmatique eut été d’affecter un stagiaire à cette tâche et de lui demander de prendre le projet et de tout transcrire dans un fichier Excel.
Mais, évidemment, je n’ai pas pour habitude de procéder de la sorte et j’avais besoin de la liste très rapidement.

Je me suis donc tourné vers PowerShell car je sais qu’il y a une extension pour SQL Server et plus précisément pour Analysis Services.

Ce billet n’a pas pour but de vous apprendre PowerShell mais de vous montrer les commandes utiles pour fouiller dans SSAS.

Pour commencer, il faut charger les commandes SSAS :

[Reflection.Assembly]::LoadWithPartialName
("Microsoft.AnalysisServices")

Ensuite, on se connecte au serveur (vous noterez que j’utilise des variables – $server, $cubeid, etc.)

$server = New-Object Microsoft.AnalysisServices.Server
$server.connect($servername)

Ensuite, on récupère le cube dans la bonne base de données

$cube = $server.Databases.Item($database).Cubes.Item($cubeid)

Enfin, je n’ai plus qu’à itérer sur les groupes de mesures pour récupérer les données

foreach ($mg in $cube.MeasureGroups)
{
    foreach ($dim in $mg.Dimensions) {
        foreach ($attr in $dim.CubeDimension.Attributes) {
            $row = $mg.Name + ‘,’+
             $mg.ID + ‘,’+
             $dim.Dimension.Name + ‘,’ +
             $dim.Dimension.ID + ‘,’ +
             $dim.GetType().ToString()
            $row | out-file -append $filename
        }
    }
}

Le modèle objet d’Analysis Services n’est pas compliqué même si ce n’est pas trivial non plus.
Vous pouvez trouver des informations sur ce modèle dans la MSDN ici : http://msdn.microsoft.com/fr-fr/library/microsoft.analysisservices.cube(v=SQL.105).aspx

Editions SQL Server Analysis Services

12 mai 2010

J’ai récemment suivi un débat sur le moyen de freiner les développeurs afin qu’ils s’en tiennent aux fonctionnalités de l’édition en production (ie. l’édition Standard).

Avec SQL Server, il est difficile de bloquer les développeurs pendant la phase de réalisation. Avec Analysis Services, il existe un moyen.

Dans le propriétés du projet, on peut en effet viser l’édition cible.

image

On obtient dans certains onglets un avertissement nous mettant en garde de l’indisponibilité de la fonctionnalité en édition standard.

 image

Cependant, cet avertissement n’est pas levé sur toutes les fonctionnalités… En effet, on peut mettre des mesures semi-additives ou non-additives sans avoir un seul warning :-( .

Vous comprendrez ma déception en fin de journée après avoir constaté qu’un agrégat de type DistinctCount ne fonctionnait pas en production alors qu’il marchait très bien sur ma plate-forme de développement.

Je savais pour LastNonEmpty mais maintenant, j’ai appris par cœur les types d’agrégats et les éditions qui les supportent.

 

Pour soutenir cette feature sur Connect :
https://connect.microsoft.com/SQLServer/feedback/details/558728/add-warning-in-bids-when-using-semiadditive-or-nonadditive-aggregate-in-standard-edition-target

Erreur de déploiement Analysis Services

25 mars 2010

 

En travaillant sur un projet SSAS avec quelques collègues, nous avons bloqué sur cette erreur au déploiement :

image

L’erreur système suivante s’est produit : .

The following system error occurred : .

Une petite lumière s’est allumée dans ma mémoire car je l’avais déjà eu. Mais mon seul souvenir est que j’avais galéré – ça s’annoncait mal.

Après de longues heures de recherche, même si nous tournions autour d’un problème de sécurité (SID), nous n’avons toujours pas trouvé.

Heureusement, un collègue (merci Philippe) s’est souvenu de la résolution. En fait, il fallait juste supprimer (ou corriger) les attributions de rôle pour ne pas pointer sur des utilisateurs “fantômes” (ie. hors du domaine).

image


Suivre

Get every new post delivered to your Inbox.

Joignez-vous à 203 followers