Le modèle multidimensionnel, exposé à travers MDX, offre aux utilisateurs finaux un moyen très pratique d'interroger des données. Une fois le modèle créé, les utilisateurs peuvent simplement glisser-déposer des champs et laisser le moteur s'occuper des calculs.
L'idée est que vous n'avez plus à vous soucier de la technologie sous-jacente, « Il suffit d'analyser. » C'est le discours habituel, et même si c'est plus ou moins vrai, la réalité est plus nuancée.
Où le modèle montre ses fissures
Aussi puissant que soit le modèle dimensionnel, il présente des inconvénients. Une solution triviale mais courante est la calcul d'une moyenne pondérée.
- MDX prend techniquement en charge les moyennes pondérées, mais uniquement sur la base des membres des dimensions, et non au niveau des lignes.
- Les performances se dégradent lorsque vous utilisez en moyenne des centaines de milliers (voire des millions) d'articles.
- Par défaut, MDX gère les sommes, les comptes et les moyennes, mais pas les moyennes pondérées basées sur des lignes.
Solution de contournement habituelle :
- Ajoutez une colonne calculée au niveau de la ligne (valeur × poids).
- Lorsque le modèle est agrégé, divisez les produits additionnés par le poids total.
Cela fonctionne, mais c'est maladroit, sujet aux erreurs et alourdit le modèle.
Et c'est juste étui facile. Les exigences du monde réel nécessitent souvent une logique qui ne fonctionne pas correctement avec l'OLAP « Agréger d'abord, calculer ensuite » philosophie.
Scénarios plus complexes
1. Conversions de devises (FX)
Les transactions financières enregistrées dans plusieurs devises nécessitent conversion au niveau des lignes avant l'agrégation.
- Si vous additionnez les transactions en euros et que vous appliquez ensuite un taux de change « moyen » au moment de la requête, les résultats sont erronés.
- La précision nécessite d'abord d'appliquer le taux de change quotidien correct par ligne, puis de procéder à l'agrégation.
2. Ajustements en fonction du temps
Les valeurs doivent souvent être ajustées en fonction de facteurs qui évoluent au fil du temps :
- Coefficients réglementaires
- Facteurs d'inflation
- Multiplicateurs spécifiques au produit
S'ils sont appliqués au niveau agrégé, les résultats sont faussés. Chaque ligne doit être multipliée par son facteur avant le cumul.
3. Gestion immobilière (cas client)
Un autre scénario dépendant du temps est lorsque les valeurs sont valides pour toutes les dates comprises entre une date de début et une date de fin données.
Un client du monde réel a stocké les données de location d'un bien immobilier dans un modèle basé sur le delta : seules les modifications (augmentation du loyer, modification des coûts de chauffage, etc.) ont été enregistrées.
Mais dans les rapports, des montants mensuels sont requis. Solutions de contournement actuelles :
- Pré-calculez valeurs complètes pour chaque mois (coût de mémoire énorme).
- Fonction Java MDX personnalisée avec des vecteurs icCube (gestion des valeurs nulles compliquée et délicate).
Les deux sont des compromis. Ce qu'il faut, c'est agrégation au niveau des lignes directement dans le modèle.
La solution : la rencontre entre MDX++ et Tabular
La version 9 introduit une fonctionnalité qui permet aux utilisateurs de définir un objet qui agrège les données ligne par ligne en utilisant les colonnes définies dans la table de faits d'un groupe de mesures.
- Les agrégations sont définies dans Code Java.
- Compilé et optimisé comme le moteur interne de icCube.
- Fini les modèles gonflés ni les prétraitements.
Vous pouvez maintenant définir une logique au niveau des lignes dans le modèle tabulaire lui-même. Le moteur effectue l'agrégation automatiquement.
Résultats pratiques
- Moyennes pondérées → Le moteur gère la valeur × le poids + le poids en interne → le ratio correct à chaque fois.
- Conversions de devises → Montant de chaque ligne × taux de change quotidien appliqué au niveau de la ligne → totaux précis.
- Ajustements basés sur le temps → Multiplicateurs appliqués par ligne → résultats cohérents dans le temps.
- Gestion immobilière → Le stockage basé sur Delta devient des valeurs mensuelles sans surcharge de mémoire.
Ajouter un agrégateur de tables
Cette fonctionnalité est toujours alpha, vous aurez donc besoin d'un peu de code Java.
Étape 1 : Création d'une classe moyenne pondérée
public class WeightedAverage implements IOlapFactTableAggregatorFactory {
@Override
public IOlapFactTableAggregator newInstance() {
return new IOlapFactTableAggregator() {
int weightIdx;
int valueIdx;
double weightedSum = 0;
double weight = 0;
@Override
public String getName() {
return "WeightedAverage";
}
@Override
public void init(IFactTableContext namesToArrayPosition, String measureName, String factColumnName) {
weightedSum = weight = 0;
weightIdx = namesToArrayPosition.getFromColumnName("weight");
valueIdx = namesToArrayPosition.getFromColumnName("amount");
}
@Override
public boolean onRow(int rowNumber, IOlapFactsTableRow row) {
final double w = row.getAsDouble(weightIdx);
weight += w;
weightedSum += w * row.getAsDouble(valueIdx);
return true;
}
@Override
public OlapScalarEntity asScalarEntity() {
return weight == 0
? null
: new OlapNumericEntity(weightedSum / weight);
}
};
}
}
Étape 2 : Ajouter une classe à plugin.xml
<tableAggregator name="WeightedAverage" className="com.myamazing.WeightedAverage"/>
Étape 3 : remplacer l'agrégation dans MDX
CREATE SET_TABLE_AGGREGATOR [Measures].[Weighted Amount] ‘WeightedAverage’
Résultat
Les analystes bénéficient toujours de la simplicité du glisser-déposer, mais avec des calculs respectueux complexité des données dans le monde réel.
- Plus de raccourcis « assez bons ».
- Juste des chiffres précis, à chaque fois.
L'avenir
- Ajoutez la possibilité de définir la classe directement dans le schéma.
- Étendez le langage pour autoriser une syntaxe telle que :
MEASURE [Weighted Amount] AS
AGGREGATE ROWS SUM([amount] * [weight]) / SUM([weight])
Ce blog a été écrit à l'aide d'une IA. Aucune IA n'a été endommagée au cours du processus (juste quelques processeurs surchauffés).