Dimensions, attributs et hiérarchies
Une dimension est un regroupement d’attributs liés — les axes selon lesquels vous découpez dans une requête. La dimension [Customer] peut contenir [Gender], [City] et [Country] ; la dimension [Time] contient [Year], [Quarter], [Month] et [Day]. Cette page couvre chaque aspect de la création de dimensions dans Mondrian 4, de la dimension à une seule table la plus simple aux jointures snowflake, fonctions temporelles, propriétés de membre et indications d’optimisation SQL.
Dimensions et attributs
Une dimension est déclarée avec un élément <Dimension>. Elle a toujours :
- un
name— le nom MDX utilisé dans les requêtes - une
table— la table de base de données (ou alias) d’où la dimension est tirée - une
key— le nom de l’attribut qui identifie de manière unique chaque ligne
Customer: table: "customer" key: "Id" attributes: - name: "Gender" - name: "Id"<Dimension name="Customer" table="customer" key="Id"> <Attributes> <Attribute name="Gender" column="gender"/> <Attribute name="Id" column="customer_id"/> </Attributes></Dimension>Chaque <Attribute> à l’intérieur de <Attributes> devient indépendamment interrogeable en MDX. Mondrian génère automatiquement une hiérarchie d’attribut à un seul niveau pour chaque attribut (voir Hiérarchies d’attribut ci-dessous), donc vous pouvez commencer à utiliser les attributs dans les requêtes sans définir explicitement aucun élément <Hierarchy>.
Clé de dimension
Chaque dimension doit avoir un attribut clé — l’attribut dont les valeurs identifient de manière unique chaque ligne dans la table de dimension. Vous le déclarez avec l’attribut key sur <Dimension>, qui doit correspondre au name de l’un des attributs dans <Attributes>.
Par exemple, dans la dimension [Customer] ci-dessus, key="Id" pointe vers <Attribute name="Id" column="customer_id"/>. L’attribut clé est utilisé lors de la liaison de la dimension à une table de faits via <ForeignKeyLink>.
Clé et nom d’attribut
La clé d’un attribut est la colonne (ou les colonnes) qui identifient de manière unique un membre. Par défaut, le nom de l’attribut — la chaîne affichée aux utilisateurs — est aussi la clé. Vous pouvez le substituer :
attributes:- name: "Month" key: - "the_year" - "month" name_column: "month_name" order_by_column: "month"<Attribute name="Month" nameColumn="month_name" orderByColumn="month"> <Key> <Column name="the_year"/> <Column name="month"/> </Key></Attribute>Concepts clés :
column(ou un bloc imbriqué<Key>/<Column>) — la ou les colonnes qui identifient le membre. Une clé composite garantit que les membres dans deux années différentes qui partagent le même nom (par ex.Q1) sont traités comme des membres séparés.nameColumn— la colonne à afficher. Si omise, la clé (dernière colonne dans une clé composite) est utilisée.orderByColumn— la colonne contrôlant l’ordre de tri. Si omise, les membres sont triés par nom.captionColumn— la colonne pour la légende, si différente du nom.
Ordre des attributs
Par défaut, les attributs sont triés par leur nom. Ce n’est pas toujours ce que vous voulez. Considérez l’attribut [Month] — si les noms de mois sont stockés sous forme de chaînes, l’ordre alphabétique donne April, August, December… plutôt que January, February, March…
Corrigez cela en définissant orderByColumn sur la colonne numérique du mois :
attributes:- name: "Month" key: - "the_year" - "month" name_column: "month_name" order_by_column: "month"<Attribute name="Month" nameColumn="month_name" orderByColumn="month"> <Key> <Column name="the_year"/> <Column name="month"/> </Key></Attribute>Avec orderByColumn="month" pointant sur la colonne numérique 1..12, Mondrian trie par le numéro mais affiche le nom lisible par humain.
Hiérarchies et niveaux
Certains attributs sont naturellement utilisés ensemble. Un utilisateur métier visualisant un état veut souvent l’étendre pour voir les villes. Visualisant un mois, il pourrait vouloir rouler en haut vers le trimestre ou l’année. Pour de telles combinaisons, vous définissez une hiérarchie.
Une hiérarchie est une liste ordonnée d’attributs — plus grossière en haut, plus fine en bas. Chaque entrée dans la hiérarchie est un niveau.
Time: table: "time_by_day" key: "Day" attributes: - name: "Year" - name: "Quarter" key: - "the_year" - "quarter" - name: "Month" key: - "the_year" - "month_of_year" - name: "Week" key: - "the_year" - "week_of_year" - name: "Day" hierarchies: - name: "Yearly" has_all: false levels: - "Year" - "Quarter" - "Month" - "Day" - name: "Weekly" has_all: false levels: - "Year" - "Week" - "Day"<Dimension name="Time" table="time_by_day" key="Day"> <Attributes> <Attribute name="Year" column="the_year"/> <Attribute name="Quarter"> <Key> <Column name="the_year"/> <Column name="quarter"/> </Key> </Attribute> <Attribute name="Month"> <Key> <Column name="the_year"/> <Column name="month_of_year"/> </Key> </Attribute> <Attribute name="Week"> <Key> <Column name="the_year"/> <Column name="week_of_year"/> </Key> </Attribute> <Attribute name="Day" column="time_id"/> </Attributes> <Hierarchies> <Hierarchy name="Yearly" hasAll="false"> <Level attribute="Year"/> <Level attribute="Quarter"/> <Level attribute="Month"/> <Level attribute="Day"/> </Hierarchy> <Hierarchy name="Weekly" hasAll="false"> <Level attribute="Year"/> <Level attribute="Week"/> <Level attribute="Day"/> </Hierarchy> </Hierarchies></Dimension>Chaque <Level attribute="..."/> référence un attribut par son nom. Les définitions d’attributs font la majeure partie du travail ; la hiérarchie n’est qu’une déclaration des attributs que vous voulez et dans quel ordre.
Concevoir des attributs pour utilisation dans des hiérarchies
La règle clé pour les hiérarchies : chaque attribut doit être fonctionnellement dépendant de l’attribut du niveau en dessous. Cela signifie qu’il doit y avoir exactement un Quarter pour tout Month donné, et exactement un Year pour tout Quarter donné.
Une hiérarchie Year → Month → Week → Day violerait cette règle, car certains jours de la Semaine 5 appartiennent à janvier et certains à février.
La conséquence pratique est que la plupart des attributs d’une hiérarchie ont besoin de clés composites pour capturer la relation parent-enfant. Si votre attribut Quarter n’a que 4 membres (parce que vous avez oublié d’inclure the_year dans sa clé), la séquence de niveaux sera 10, 4, 120, 3652 — une séquence non croissante qui signale une erreur de modélisation.
Ordre et affichage des niveaux
L’attribut orderByColumn sur <Attribute> contrôle comment les membres d’un niveau sont triés. Le nameColumn contrôle la chaîne d’affichage. Ces deux attributs sont indépendants : vous pouvez trier par une colonne numérique et afficher une colonne de nom lisible par humain.
Les colonnes ordinales peuvent être de n’importe quel type de données utilisable dans une clause ORDER BY. L’ordre est scoped par parent — une colonne day_in_month cycle de 1 à 28-31 dans chaque mois.
L’attribut type sur <Attribute> (valeurs : String, Integer, Numeric, Boolean, Date, Time, Timestamp) indique à Mondrian comment générer le SQL pour la clé de cet attribut. Le défaut est Numeric. Si la clé est une chaîne, Mondrian doit le savoir pour pouvoir entourer les valeurs de guillemets simples :
WHERE productSku = '123-455-AA'Membres « All » et par défaut
Par défaut, chaque hiérarchie contient un niveau supérieur appelé (All), qui contient un seul membre appelé (All {hierarchyName}). Ce membre est le parent de tous les autres membres et représente un grand total. C’est aussi le membre par défaut — le membre utilisé lorsque la hiérarchie est absente des axes de la requête.
Vous pouvez personnaliser ce comportement avec des attributs sur <Hierarchy> :
| Attribut | Description |
|---|---|
hasAll | Si le niveau (All) existe. Par défaut true. |
allMemberName | Nom du membre all. Par défaut "All {hierarchyName}". |
allLevelName | Nom du niveau all. Par défaut "(All)". |
defaultMember | Nom MDX entièrement qualifié du membre par défaut. |
<Hierarchy name="Yearly" hasAll="false" defaultMember="[Time].[1997].[Q1].[1]"> ...</Hierarchy>Lorsque hasAll="false", le membre par défaut devient le premier membre du premier niveau — pour une hiérarchie Time, la première année dans les données. Cela peut causer des résultats inattendus lorsque cette hiérarchie n’est pas sur un axe, donc préférez hasAll="true" sauf si vous avez une raison spécifique.
Lorsque defaultMember est défini, ce peut même être un membre calculé.
Hiérarchies d’attribut
MDX ne connaît pas les attributs — il ne connaît que les dimensions, hiérarchies, niveaux et membres. Mondrian comble le fossé en générant automatiquement une hiérarchie à un seul niveau pour chaque attribut, appelée hiérarchie d’attribut.
Les hiérarchies d’attribut fonctionnent exactement comme les hiérarchies déclarées manuellement. Elles vous laissent exposer une douzaine d’attributs et commencer à les interroger immédiatement, sans écrire d’éléments <Hierarchy>.
Pour contrôler une hiérarchie d’attribut, utilisez les attributs suivants sur <Attribute> :
Attribut <Hierarchy> | Attribut <Attribute> | Description |
|---|---|---|
| N/A | hasHierarchy | Si une hiérarchie d’attribut est générée. Par défaut : true. |
name | N/A | Égale toujours le nom de l’attribut. |
hasAll | hierarchyHasAll | Si la hiérarchie a un niveau (All). Par défaut : true. |
allMemberName | hierarchyAllMemberName | Nom du membre all. |
allMemberCaption | hierarchyAllMemberCaption | Légende du membre all. |
allLevelName | hierarchyAllLevelName | Nom du niveau all. |
defaultMember | hierarchyDefaultMember | Nom MDX entièrement qualifié du membre par défaut. |
Attributs versus hiérarchies
Dans Mondrian 3, les hiérarchies étaient verbeuses à définir et la syntaxe MDX était maladroite lorsqu’une dimension avait plus d’une hiérarchie. En conséquence, la plupart des schemas exposaient les dimensions comme une seule hiérarchie et traitaient les niveaux individuels comme l’unité d’analyse.
Mondrian 4 encourage une approche différente : concevez avec de nombreux attributs, ajoutez des hiérarchies uniquement là où elles sont utiles.
- Définissez des attributs pour chaque colonne selon laquelle vous voulez découper.
- Laissez les utilisateurs explorer le cube.
- Lorsque vous remarquez que certaines combinaisons d’attributs sont toujours utilisées ensemble (par ex. Year → Quarter → Month), créez une hiérarchie pour ce chemin de drill.
- Les utilisateurs utiliseront toujours des attributs autonomes la plupart du temps.
Une nuance : certains attributs ont des variantes intra-parent et sans parent. Par exemple, [Time].[Month] (120 membres sur 10 ans) est différent de [Time].[Month of Year] (12 membres). Le premier vous permet de comparer décembre 2012 avec décembre 2011 ; le second vous permet de comparer décembre avec avril sur toutes les années. Vous avez besoin de deux attributs séparés. Une convention de nommage comme "X of Parent" aide les utilisateurs à comprendre lequel est lequel.
Raccourcis de schema
Le XML peut être verbeux. Mondrian fournit des raccourcis pour garder les choses simples concises.
Attribut comme raccourci pour un élément imbriqué singleton
Lorsqu’un attribut a une clé mono-colonne, vous pouvez écrire :
<Attribute name="A" column="c"/>au lieu de la forme plus longue :
<Attribute name="A"> <Key> <Column name="c"/> </Key></Attribute>Lorsqu’une clé composite ou une référence de colonne inter-tables est nécessaire, utilisez la forme imbriquée <Key>.
Le même pattern de raccourci s’applique dans le schema :
| Élément parent | Attribut raccourci | Élément imbriqué équivalent | Description |
|---|---|---|---|
<Attribute> | keyColumn | <Key> | Colonne(s) qui composent la clé de cet attribut. |
<Attribute> | nameColumn | <Name> | Colonne affichée comme nom du membre. Par défaut la clé. |
<Attribute> | orderByColumn | <OrderBy> | Colonne(s) qui définissent l’ordre de tri. Par défaut la clé. |
<Attribute> | captionColumn | <Caption> | Colonne qui forme la légende. Par défaut le nom. |
<Measure> | column | <Arguments> | Colonne(s) passée(s) à la fonction d’agrégat SQL. |
<Table> | keyColumn | <Key> | Colonne(s) formant la clé primaire de la table. |
<Link> | foreignKeyColumn | <ForeignKey> | Colonne(s) formant la clé étrangère de la table référençant un lien. |
<ForeignKeyLink> | foreignKeyColumn | <ForeignKey> | Colonne(s) liant la table de faits d’un groupe de mesures à une table de dimension. |
Attribut table hérité
L’attribut table sur <Dimension>, <Attribute> et <Column> est hérité de l’élément englobant lorsqu’il n’est pas explicitement défini. Cela rend les dimensions à table unique concises — déclarez table une fois sur <Dimension> et chaque <Attribute> à l’intérieur en hérite automatiquement.
Dimensions partagées
Si plusieurs cubes dans le même schema utilisent des dimensions avec la même définition, définissez une dimension partagée au niveau du schema et référencez-la depuis chaque cube.
La dimension Measures
Les mesures sont traitées comme des membres d’une dimension spéciale appelée Measures. Elle a une seule hiérarchie et un seul niveau. Parce qu’il n’y a qu’une seule hiérarchie, MDX vous laisse omettre le nom de la hiérarchie :
[Measures].[Unit Sales]est un raccourci pour :
[Measures].[Measures].[Unit Sales]Ce design signifie que vous pouvez changer le contexte de mesure dans un calcul aussi facilement que vous changez une période de temps ou une région de ventes — cela permet une plus grande réutilisation de formules et rend le contrôle d’accès plus simple (une autorisation sur une cellule est une coordonnée tridimensionnelle : cube × tranche de dimension × mesure).
Dimensions en étoile et en snowflake
Dimensions en étoile
Les dimensions vues jusqu’à présent tirent toutes leurs colonnes d’une seule table. Elles sont appelées dimensions en étoile car elles rayonnent depuis la table de faits comme les pointes d’une étoile.
Dimensions snowflake
Une dimension snowflake couvre deux ou plusieurs tables de dimension jointes ensemble. Avant d’en définir une, assurez-vous :
- Chaque table dans le snowflake est déclarée dans le
<PhysicalSchema>. - Un élément
<Link>existe pour chaque jointure entre tables dans le snowflake.
Voici la paire product et product_class utilisée pour construire la dimension [Product] :
tables:- name: "product" key_column: "product_id"- name: "product_class" key_column: "product_class_id"links:- source: "product_class" target: "product" foreign_key_column: "product_class_id"<Table name="product" keyColumn="product_id"/><Table name="product_class" keyColumn="product_class_id"/><Link target="product" source="product_class" foreignKeyColumn="product_class_id"/>Puis définissez la dimension, en spécifiant les substitutions de table au niveau de l’attribut là où c’est nécessaire :
Product: table: "product" key: "Product Id" attributes: - name: "Product Family" table: "product_class" key_column: "product_family" - name: "Product Department" table: "product_class" key: - "product_family" - "product_department" - name: "Brand Name" table: "product_class" key: - "product_family" - "product_department" - "product_class.brand_name" - name: "Product Name" table: "product" key_column: "product_id" name_column: "product_name" - name: "Product Id" table: "product" key_column: "product_id"<Dimension name="Product" table="product" key="Product Id"> <Attributes> <Attribute name="Product Family" table="product_class" keyColumn="product_family"/> <Attribute name="Product Department" table="product_class"> <Key> <Column name="product_family"/> <Column name="product_department"/> </Key> </Attribute> <Attribute name="Brand Name" table="product_class"> <Key> <Column name="product_family"/> <Column name="product_department"/> <Column table="product_class" name="brand_name"/> </Key> </Attribute> <Attribute name="Product Name" table="product" keyColumn="product_id" nameColumn="product_name"/> <Attribute name="Product Id" table="product" keyColumn="product_id"/> </Attributes></Dimension>L’attribut table cascade : <Dimension table="product"> définit le défaut, <Attribute table="product_class"> le substitue, et <Column table="product_class"> substitue à nouveau. Mondrian signalera une erreur s’il n’y a pas de chemin entre les tables, ou s’il y a plus d’un chemin.
Dimensions temporelles
MDX inclut des fonctions sensibles au temps — ParallelPeriod, PeriodsToDate, WTD, MTD, QTD, YTD, LastPeriod — qui ne fonctionnent correctement que lorsque Mondrian sait quels attributs représentent des périodes de temps.
Déclarez une dimension temporelle en ajoutant type="TimeDimension" à <Dimension>. Puis marquez chaque attribut avec une valeur levelType :
Valeur levelType | Signification |
|---|---|
TimeYears | Année |
TimeHalfYear | Demi-année |
TimeQuarters | Trimestre |
TimeMonths | Mois |
TimeWeeks | Semaine |
TimeDays | Jour |
TimeHours | Heure |
TimeMinutes | Minute |
TimeSeconds | Seconde |
Une dimension temporelle complète ressemble à ceci :
<Dimension name="Time" table="time_by_day" key="Day" type="TimeDimension"> <Attributes> <Attribute name="Year" keyColumn="the_year" levelType="TimeYears"/> <Attribute name="Quarter" levelType="TimeQuarters"> <Key> <Column name="the_year"/> <Column name="quarter"/> </Key> </Attribute> <Attribute name="Month" levelType="TimeMonths" nameColumn="month_name" orderByColumn="month_of_year"> <Key> <Column name="the_year"/> <Column name="month_of_year"/> </Key> </Attribute> <Attribute name="Week" levelType="TimeWeeks"> <Key> <Column name="the_year"/> <Column name="week_of_year"/> </Key> </Attribute> <Attribute name="Day" keyColumn="time_id" levelType="TimeDays"/> </Attributes> <Hierarchies> <Hierarchy name="Yearly" hasAll="true" allMemberName="All Periods"> <Level attribute="Year"/> <Level attribute="Quarter"/> <Level attribute="Month"/> <Level attribute="Day"/> </Hierarchy> </Hierarchies></Dimension>Attributs Tier et Duration
Deux formes d’attribut sont calculées à partir des colonnes sous-jacentes plutôt que lues directement depuis une colonne clé. Toutes deux sont des extensions Saiku à Mondrian 4 (issue #108) : elles désucrient en une expression SQL par dialecte rendue par le backend Calcite, vous obtenez donc les membres binnés/dérivés sans modéliser une table d’aide ou une vue.
Tier (binning)
Un <Tier> transforme une colonne numérique en un petit ensemble de bins ordonnés et nommés — l’équivalent natif de schema pour type: tier de LookML. Chaque bin sauf le dernier porte une boundary numérique (sa borne supérieure exclusive) ; une ligne prend l’étiquette du premier bin dont la frontière est strictement supérieure à sa valeur. Le bin final omet boundary et capture tout au-dessus ou égal à la dernière borne. Les membres trient par ordre de frontière, pas lexicalement.
attributes:- name: "Size Tier" tier: column: "units" bins: - boundary: 10 label: "Small" # units < 10 - boundary: 100 label: "Medium" # 10 ≤ units < 100 - label: "Large" # units ≥ 100 (open-ended)<Attribute name="Size Tier"> <Tier column="units"> <Bin boundary="10" label="Small"/> <!-- units < 10 --> <Bin boundary="100" label="Medium"/> <!-- 10 ≤ units < 100 --> <Bin label="Large"/> <!-- units ≥ 100 (open-ended) --> </Tier></Attribute>column est requis ; un table facultatif sélectionne la table source quand ce n’est pas la propre table de l’attribut (ou de la dimension).
Duration
Un <Duration> calcule un intervalle numérique entre deux colonnes date/timestamp dans une unit fixe — l’équivalent de dimension_group: { type: duration } de LookML. Les membres sont des nombres et trient numériquement.
attributes:- name: "Lead Time (months)" duration: start_column: "order_date" end_column: "ship_date" unit: "MONTH"<Attribute name="Lead Time (months)"> <Duration startColumn="order_date" endColumn="ship_date" unit="MONTH"/></Attribute>startColumn et endColumn sont requis ; unit est l’un de DAY (par défaut), WEEK, MONTH, QUARTER, YEAR, HOUR, MINUTE, SECOND. Un table facultatif sélectionne la table source.
Propriétés de membre
Les propriétés de membre attachent des informations supplémentaires aux membres d’un attribut — des données qui sont liées à l’attribut mais pas utilisées comme clé ou pour le regroupement. Vous les déclarez en utilisant <Property> à l’intérieur de <Attribute> :
<Attribute name="City" keyColumn="city_id"> <Property attribute="Country"/> <Property attribute="State"/> <Property attribute="City Population" name="Population"/></Attribute>Ici, l’attribut [City] gagne trois propriétés :
CountryetStatehéritent leur nom de l’attribut référencé.City Populationest référencée par nom d’attribut mais exposée commePopulationvia la substitution explicitename.
Les propriétés sont définies en termes d’autres attributs dans la même dimension. Cela signifie que chaque propriété a une clé, un nom, une légende et un ordre de tri — exactement comme tout attribut. L’attribut référencé doit être fonctionnellement dépendant de l’attribut annoté. Une propriété basée sur [Zipcode] sur [City] serait illégale — une ville peut avoir plusieurs codes postaux. Mais chaque ville a exactement un état, un pays et une valeur de population.
Vous pouvez accéder aux propriétés en MDX via :
member.Properties("propertyName")Par exemple :
SELECT {[Measures].[Store Sales]} ON COLUMNS, TopCount( Filter( [Customer].[City].Members, [Customer].[City].CurrentMember.Properties("Population") < 10000), 10, [Measures].[Store Sales]) ON ROWSFROM [Sales]Mondrian infère le type de propriété à partir de l’attribut type de la définition <Property> (String, Numeric ou Boolean) lorsque le nom de la propriété est une chaîne constante. Si vous construisez le nom de la propriété dynamiquement avec une expression, Mondrian renvoie une valeur non typée.
Dimensions dégénérées
Une dimension dégénérée est si simple qu’elle ne mérite pas sa propre table de dimension. Considérez une colonne payment_method (valeurs : Credit, Cash, ATM) située directement dans la table de faits. Créer une table de lookup séparée de trois lignes juste pour ces valeurs ajoute une jointure sans bénéfice.
Au lieu de cela, déclarez une dimension sans spécifier de table, et Mondrian lit les colonnes de la table de faits directement. En M4, vous pouvez le faire en omettant l’attribut table sur <Dimension> et en vous assurant que la column de l’attribut existe dans la table de faits :
Payment Method: key: "Payment Method" attributes: - name: "Payment Method" key_column: "payment_method"<Dimension name="Payment Method" key="Payment Method"> <Attributes> <Attribute name="Payment Method" keyColumn="payment_method"/> </Attributes></Dimension>Parce qu’il n’y a pas de jointure, vous n’avez pas besoin de colonne de clé étrangère <ForeignKeyLink> — la colonne payment_method est déjà dans la table de faits. Aucun élément <Link> n’est nécessaire non plus.
Cardinalité approximative de niveau
L’attribut approxRowCount sur <Attribute> (et sur <Level> dans les hiérarchies explicites) indique à Mondrian approximativement combien de membres distincts cet attribut a. Fournir cette indication peut améliorer significativement les performances en réduisant le besoin pour Mondrian d’exécuter des requêtes COUNT(DISTINCT ...) pour déterminer la cardinalité — particulièrement notable lors de la connexion via XMLA.
<Attribute name="Product Name" keyColumn="product_id" approxRowCount="1560"/>Attribut de mesure par défaut
L’attribut defaultMeasure sur <Cube> vous permet de spécifier explicitement quelle mesure est sélectionnée lorsqu’une requête ne référence pas la dimension [Measures]. Sans cela, Mondrian choisit la première mesure déclarée dans le cube.
Définir defaultMeasure est particulièrement utile lorsque vous voulez qu’un membre calculé soit le défaut, puisque les membres calculés sont déclarés après les mesures de base :
<Cube name="Sales" defaultMeasure="Unit Sales"> ... <CalculatedMember name="Profit" dimension="Measures"> <Formula>[Measures].[Store Sales] - [Measures].[Store Cost]</Formula> ... </CalculatedMember></Cube>Optimisations de dépendance fonctionnelle
Lorsque Mondrian génère du SQL pour peupler les membres de dimension, il utilise GROUP BY pour dédupliquer les lignes. Dans certains schemas, vous pouvez déclarer que certaines colonnes sont fonctionnellement dépendantes d’autres — éliminant les colonnes GROUP BY redondantes et améliorant les performances de requête.
Deux attributs permettent cela :
dependsOnLevelValue sur <Property>
Définir dependsOnLevelValue="true" sur une propriété indique à Mondrian que la valeur de la propriété est constante pour toute valeur de niveau donnée. Par exemple, une usine de fabrication existe dans exactement une ville et un état, donc les propriétés State et City sont fonctionnellement dépendantes du niveau ManufacturingPlant.
uniqueKeyLevelName sur <Hierarchy>
Définir uniqueKeyLevelName="Vehicle Identification Number" sur une hiérarchie indique à Mondrian que le niveau nommé — ensemble avec tous les niveaux au-dessus — agit comme une clé alternative unique. Pour toute combinaison unique de ces valeurs de niveau, il y a exactement une combinaison de valeurs pour tous les niveaux en dessous.
Exemple :
<Dimension name="Automotive"> <Attributes> <Attribute name="Make" keyColumn="make_id"/> <Attribute name="Model" keyColumn="model_id"/> <Attribute name="ManufacturingPlant" keyColumn="plant_id"/> <Attribute name="Vehicle Identification Number" keyColumn="vehicle_id"/> <Attribute name="LicensePlateNum" keyColumn="license_id"/> </Attributes> <Hierarchies> <Hierarchy name="Automotive" hasAll="true" uniqueKeyLevelName="Vehicle Identification Number"> <Level attribute="Make"/> <Level attribute="Model"/> <Level attribute="ManufacturingPlant"> <Property attribute="State"/> <Property attribute="City"/> </Level> <Level attribute="Vehicle Identification Number"> <Property attribute="Color"/> <Property attribute="Trim"/> </Level> <Level attribute="LicensePlateNum"> <Property attribute="License State"/> </Level> </Hierarchy> </Hierarchies></Dimension>Lorsque Mondrian peut confirmer que :
- La requête inclut le niveau de clé unique, et
- Toutes les propriétés dans la requête ont
dependsOnLevelValue="true"
…il peut abandonner la clause GROUP BY entièrement, ce qui est un gain de performance substantiel sur les grandes tables de dimension.
Sur les bases de données qui permettent les colonnes non groupées dans SELECT (comme MySQL), Mondrian peut appliquer une optimisation partielle même sans uniqueKeyLevelName — laissant les propriétés fonctionnellement dépendantes hors du GROUP BY tout en gardant les colonnes non dépendantes dedans.
Adapté du guide de schema du projet Mondrian, disponible sous l’Eclipse Public License v1.0.