Résoudre les manigances de l'ordre

Aujourd'hui, je vais tenir un blog sur un problème que nous avons récemment résolu dans un cube de client, une erreur dans le script Mdx qui est très facile à faire si vous ne faites pas attention.

Nous allons présenter un exemple simple dans AdventureWorks (quoi d'autre ?) pour illustrer le problème.

Le client avait déjà ajouté un calcul à son cube pour montrer la croissance d'une année sur l'autre. La formule est la suivante :

Créer le membre CurrentCube [mesures] [Delta à l'année précédente] en tant que
(
    ([Mesures]. [Montant des ventes sur Internet])
    -
    ([Mesures]. [Montant des ventes sur Internet],
        Période Parallèle(
            [Date]. [Calendrier]. [Année civile],
            1,
            [Date]. [Calendrier].Membre actuel
        )
    )
)
/
    ([Mesures]. [Montant des ventes sur Internet],
        Période Parallèle(
            [Date]. [Calendrier]. [Année civile],
            1,
            [Date]. [Calendrier].Membre actuel
        )
    )
, Format_String = "0.00%" ;

(certaines vérifications d'erreurs ont été supprimées pour plus de clarté)

Cette capture d'écran montre quelques grilles XLCubed simples montrant la valeur réelle, et en dessous du pourcentage de variation. J'ai ajouté un calcul Excel pour montrer que les résultats sont conformes aux attentes.

Plus tard au cours du développement du cube, le client a ajouté un membre calculé dans sa dimension Produit, qui donne un total excluant une des catégories de produits.

Pour reproduire cela, je vais ajouter un calcul pour "All Ex Bikes" :

Créer un membre 
CurrentCube. [Produit]. [Catégories de modèles de produits]. [Tous les produits]. [Tous les vélos Ex].
comme
(
    ([Produit]. [Catégories de modèles de produits]. [Tous les produits])
    -
    ([Produit]. [Catégories de modèles de produits]. [Catégorie].& [1])
) ;

Et si nous refaisons le rapport, nous obtenons ce qui suit.

Remarquez la cellule que j'ai mise en évidence. Le calcul "All Ex Bikes" fonctionne bien sur la mesure normale, mais il donne un chiffre totalement faux pour le calcul du pourcentage. Que se passe-t-il ?

Le problème est que, dans la cellule mise en évidence, les services d'analyse doivent tenir compte de deux calculs lorsqu'ils élaborent le résultat.

  • Comparer cette année à l'année dernière
  • Obtenez le "Grand Total", et soustrayez "Vélos"

Comme le nombre de retours est de 1,85 %, nous pouvons voir que le service d'analyse a choisi la deuxième option, "Grand Total" - "Vélos".

Ce que nous voulons vraiment, c'est que le calcul soit fait en obtenant le sous-total, puis en faisant la variation en pourcentage sur cette base.

Heureusement, la solution était simple. Les services d'analyse effectueront les calculs dans l'ordre où ils se trouvent dans le script Mdx. Pour résoudre le problème, nous avons donc simplement déplacé la nouvelle définition de "All Ex Bikes" au-dessus du calcul du pourcentage.

Le nombre de retours correspond maintenant à nos attentes.

L'ordre de passage ou de résolution peut être un sujet complexe, vous devrez donc être prudent.

Dans ce cas, le numéro est totalement faux, donc il était facile à repérer, mais certains insectes seront beaucoup plus subtils, alors attention !

Parent-Child Dimensions in Analysis Services – Performance Walkthrough

Les hiérarchies parents-enfants conviennent bien à de nombreuses structures de données telles que les comptes ou les employés, et si elles peuvent accélérer le développement dans certains cas, elles peuvent aussi causer des problèmes de performance dans les grands cubes.

Nous voyons souvent des clients qui ont ce type de problèmes de performance et nous avons pensé qu'il valait la peine de partager une technique simple pour modifier la structure des dimensions afin d'améliorer la vitesse de requête.

Le problème

Souvent, des hiérarchies parents-enfants sont créées, car c'est la structure utilisée dans la source relationnelle, et elles semblent donc bien adaptées pour modéliser les membres. Dans de nombreux cas, cependant, les données ne se trouvent qu'au niveau de la feuille de la hiérarchie, ce qui signifie que le lien parent-enfant n'est pas vraiment nécessaire.

Les problèmes de performance se produisent parce qu'aucun agrégat n'est créé pour les dimensions parent-enfant, comme le précise le guide de performance des Services d'analyse :

Hiérarchies parents-enfants

Les hiérarchies parents-enfants sont des hiérarchies à nombre variable de niveaux, déterminées par une relation récursive entre un attribut enfant et un attribut parent. Les hiérarchies parents-enfants sont généralement utilisées pour représenter un plan comptable financier ou un organigramme. Dans les hiérarchies parents-enfants, les agrégations sont créées uniquement pour l'attribut clé et l'attribut supérieur, c'est-à-dire l'attribut Tous, sauf s'il est désactivé. Il faut donc éviter d'utiliser des hiérarchies parents-enfants qui contiennent un grand nombre de membres aux niveaux intermédiaires de la hiérarchie. En outre, vous devez limiter le nombre de hiérarchies parents-enfants dans votre cube.

Si vous vous trouvez dans un scénario de conception avec une grande hiérarchie parents-enfants (plus de 250 000 membres), vous pouvez envisager de modifier le schéma source pour réorganiser une partie ou la totalité de la hiérarchie en une hiérarchie utilisateur avec un nombre fixe de niveaux. Une fois que les données ont été réorganisées dans la hiérarchie des utilisateurs, vous pouvez utiliser la propriété "Cacher le membre si" de chaque niveau pour cacher les membres redondants ou manquants.

 

Le guide de performance suggère de réorganiser la hiérarchie pour améliorer les performances, mais ne dit pas comment.

La solution

Cet article présente les étapes nécessaires pour modifier votre structure hiérarchique parents-enfants afin d'avoir de vrais niveaux, de sorte que les agrégations fonctionnent et que vos performances soient aussi bonnes que celles que vous attendez des hiérarchies normales.

Ce processus est connu sous le nom d'aplatissement ou de normalisation de la hiérarchie parent-enfant.

Tout d'abord, examinons les données de notre source relationnelle.

[spoiler intro="Code" title="Sql Create Script"]

CREER TABLE [dbo] [Produits](
 [ProductID] [int] NON NUL,
 [ParentID] [int] NUL,
 [Nom] [varchar](50) NON NUL,
 CONSTRAINT [PK_Products] CLÉ PRIMAIRE CLUSTERED ([ProductID] ASC)
)

GO

insérer dans Products(ProductID, ParentID, Name) les valeurs(1, NULL, 'All')
insérer dans les valeurs de Products(ProductID, ParentID, Name)(2, 1, 'Fruit')
insérer dans Products(ProductID, ParentID, Name) les valeurs(3, 2, 'Red')
insérer dans Products(ProductID, ParentID, Name) les valeurs(4, 3, 'Cherry')
insérer dans les valeurs de Products(ProductID, ParentID, Name)(5, 3, 'Strawberry')
insérer dans Products(ProductID, ParentID, Name) les valeurs(6, 2, 'Yellow')
insérer dans les valeurs de Products(ProductID, ParentID, Name)(7, 6, 'Banana')
insérer dans les valeurs de Products(ProductID, ParentID, Name)(8, 6, 'Lemon')
insérer dans Products(ProductID, ParentID, Name) les valeurs(9, 1, 'Meat')
insérer dans les valeurs de Products(ProductID, ParentID, Name)(10, 9, 'Beef')
insérer dans les valeurs de Products(ProductID, ParentID, Name)(11, 9, 'Pork')

[/spoiler]

Pas une grande dimension, mais suffisamment pour démontrer la technique. Comme vous pouvez le voir, mes vrais produits sont tous au niveau des feuilles.

La stratégie est assez simple :

  • Créer une vue pour séparer les membres en différents niveaux.
  • Créer une nouvelle dimension en utilisant ces niveaux réels.
  • Configurer la dimension pour qu'elle apparaisse comme la dimension parent-enfant originale, mais avec les performances d'une dimension normale.

Créer la vue

Nous voulons créer une vue dénormalisée des données. Pour ce faire, nous relions le produit à lui-même une fois pour chaque niveau. Cela signifie que nous devons connaître la profondeur maximale de la hiérarchie, mais celle-ci est souvent fixe, et nous intégrerons quelques niveaux supplémentaires pour la sécurité.

Les astuces sont ici :

  • Utilisez coalesce() pour que nous obtenions toujours l'ID de niveau le plus bas sous les feuilles, jamais un NUL. Cela nous permet de rejoindre la table des faits au niveau le plus bas de notre hiérarchie.
  • Laissez les colonnes Nom nulles en dessous des feuilles, cela nous permettra d'arrêter la hiérarchie au niveau de la feuille correcte dans chaque partie de la hiérarchie.

[spoiler intro="Code" title="Sql View Script"]

créer une vue dbo.ProductsFlattened

comme

sélectionnez P1.ProductID comme Level1ID,
 P1.Nom comme Level1Name,
 coalescent(P2.ProductID, P1.ProductID) comme Level2ID,
 P2.Nom comme Level2Name,
 coalescent(P3.ProductID, P2.ProductID, P1.ProductID) comme Level3ID,
 P3.Nom comme Level3Name,
 coalescent(P4.ProductID, P3.ProductID, P2.ProductID, P1.ProductID) comme Level4ID,
 P4.Nom comme Level4Name,
 coalescent(P5.ProductID, P4.ProductID, P3.ProductID, P2.ProductID, P1.ProductID) comme Level5ID,
 P5.Nom comme Level5Name

de dbo.Products P0
à gauche rejoindre dbo.Products P1
 sur P0.ProductID = P1.ParentID
à gauche rejoindre dbo.Products P2
 sur P1.ProductID = P2.ParentID
à gauche rejoindre dbo.Products P3
 sur P2.ProductID = P3.ParentID
à gauche rejoindre dbo.Products P4
 sur P3.ProductID = P4.ParentID
à gauche rejoindre dbo.Products P5
 sur P4.ProductID = P5.ParentID

où P0.ParentID est nul

[/spoiler]

On a le droit de faire tourner ça :

Nous pouvons évidemment actualiser cette vue pour créer d'autres niveaux selon les besoins, mais 5 suffisent pour l'instant.

La dimension

Ensuite, nous allons à BIDS, et nous ajoutons la vue à notre vue de la source de données, puis nous ajoutons une nouvelle dimension basée sur la vue.

Les étapes clés pour créer correctement la dimension sont les suivantes :

  • Définissez l'attribut clé à Level5ID, et le nom à Level5Name.
  • Créez un attribut pour chaque ID de niveau, et pour chacun d'eux, définissez la colonne Nom de manière appropriée.
  • Créez une hiérarchie en utilisant ces attributs dans l'ordre.
  • Pour chaque attribut, définissez AttributeHierarchyVisible to False.
  • A chaque niveau de la hiérarchie, mettez HideMemberIf à NoName.
  • Établir les relations d'attributs entre les niveaux.

Vous devriez aboutir à ce qui suit :

Structure des dimensions

 

Relations d'attributs

 

Si vous parcourez la dimension, vous verrez qu'elle ne va jamais jusqu'au niveau 5, même si elle existe. Cela est dû au fait que nous avons configuré l'option de masquage des membres et que nous avons renvoyé des NULL à notre avis.

Conclusion

Et c'est fait, vous pouvez maintenant rejoindre vos tableaux d'information au niveau le plus bas, construire votre cube comme d'habitude et bénéficier des avantages de l'agrégation en termes de performance !

Voir aussi

Un outil permettant d'atteindre le même résultat est disponible auprès du Codeplex, nous ne l'avons pas personnellement essayé mais il pourrait bien être un gain de temps. Il fonctionne de manière similaire à l'exemple ci-dessus, mais il est souvent utile de comprendre comment quelque chose fonctionne, même si vous choisissez de l'automatiser.

Data sources for Excel dashboards: avoid spreadsheet hell

C'est le premier de deux billets jumeaux où nous parlerons de l'alpha et de l'oméga des tableaux de bord Excel : l'accès aux données et la publication des tableaux de bord. Ce sont deux points faibles d'Excel, et il faut les aborder avec précaution lors de la planification d'un nouveau tableau de bord. Commençons par passer en revue les options d'accès aux données disponibles.

Copier / Coller des données

Est-ce que vous ou quelqu'un de votre organisation remplissez manuellement la feuille de calcul ? Ou bien copiez-vous ou collez-vous les données dans le tableur ? C'est la méthode la plus simple pour introduire des données dans Excel, mais elle peut être dangereuse. Il convient de l'éviter lorsque de meilleures options sont disponibles.

Lorsque vous avez affaire à une sorte de gestion structurée des données (comme c'est le cas lorsque vous créez un tableau de bord), vous devez planifier à l'avance et vous assurer que lorsque les données changent, cela ne casse pas votre tableau de bord bien conçu. Chaque fonction, chaque tableau, doit savoir où se trouvent les données et s'adapter à ces changements si nécessaire.

Lorsque vous collez des données, il y a un risque élevé de casser quelque chose. Le nombre de lignes ou de colonnes dans le nouvel ensemble de données peut changer, et des éléments comme un graphique de séries chronologiques peuvent ne pas reconnaître les nouvelles périodes et vous devrez probablement mettre à jour les références manuellement. Là encore, planifiez soigneusement ou vous vous retrouverez dans un enfer de maintenance.

Table extérieure

Vous pouvez créer un lien vers une table externe dans Access, Oracle ou un autre outil de base de données via une connexion ODBC standard. Cela permettra de s'assurer que les données sont correctement canalisées dans le tableur, mais avec des données réelles, il est très facile d'avoir plus d'enregistrements que la limite de 65 536 lignes d'Excel 2003. Vous serez mieux si vous ne vous connectez pas aux données brutes elles-mêmes mais à une requête/vue qui agrège les données (l'une des règles de base pour la conception de tableaux de bord dans Excel est d'éviter les calculs et les données dérivées ; les données doivent provenir de la source déjà préparée pour être affichée).

Une fois que les données sont dans Excel, il n'y a pas beaucoup de différence entre cette option et la précédente. Vous devez toujours utiliser les fonctions de recherche pour récupérer les données et les utiliser dans les tableaux et graphiques du rapport, et l'intégrité des données est une chose stressante que vous devez garantir en permanence. Dans la mesure du possible, utilisez des fonctions de base de données comme DSUM au lieu de fonctions de recherche (un article sera consacré à ce sujet).

Tableaux croisés dynamiques

Pour une installation Excel prête à l'emploi, vous pouvez envisager des tableaux croisés dynamiques. Ils constituent une option intéressante pour les petits ensembles de données et ils présentent une courbe d'apprentissage initiale agréablement plate. Veuillez noter que les tableaux croisés dynamiques augmenteront considérablement la taille de votre fichier car ils stockent toutes les données dans le tableur, ce qui peut poser un problème d'extensibilité. De plus, ils fonctionnent mieux avec une structure de données hiérarchique stricte. Si vos données ne correspondent pas exactement à ce concept, cela peut poser un problème. Si vous disposez d'un ensemble de données plus important, vous devriez plutôt envisager un cube OLAP.

Cubes OLAP

Le concept d'un cube OLAP peut être quelque chose d'effrayant pour l'utilisateur moyen d'Excel, mais une fois que vous commencez à les utiliser, vous ne reviendrez jamais en arrière. Vous utilisez en particulier ce que Charley Kid appelle un "cube OLAP convivial pour Excel".

Contrairement aux autres méthodes, un cube OLAP compatible avec Excel (comme XLCubed) ne stockera pas les données dans le tableur, ce qui élimine le besoin des méthodes habituelles de rafraîchissement des données (ouvrir le tableau de bord, rafraîchir, sauvegarder et fermer). Le cube est automatiquement mis à jour et vous pouvez l'interroger en utilisant des formules similaires à GETPIVOTDATA. Cela a un impact énorme sur votre façon de travailler. Vous bénéficiez de tous les avantages d'un tableau croisé dynamique ordinaire, ainsi que de plusieurs options qui vous sauveront la vie. Le tableau de bord sera plus simple, plus propre et plus facile à entretenir.

Dernières réflexions

Vous disposez de plusieurs méthodes pour la gestion des données dans Excel, et vous devez décider quelle est la meilleure méthode pour chaque tableau de bord spécifique. L'extensibilité est toujours un problème, alors assurez-vous que vos données ne dépassent pas la méthode choisie. Un cube OLAP compatible avec Excel peut nécessiter un investissement immédiat, mais vous évitera bien des soucis à long terme.

La gestion des données dans Excel est un facteur essentiel, qui sera examiné en détail dans les prochains postes.

Le post suivant traite de l'autre extrémité d'un projet de tableau de bord : comment mettre le tableau de bord à la disposition des utilisateurs.