Zum Inhalt springen

Dimensionen, Attribute und Hierarchien

Eine Dimension ist eine Gruppierung verwandter Attribute — die Achsen, nach denen Sie in einer Abfrage schneiden. Die [Customer]-Dimension könnte [Gender], [City] und [Country] enthalten; die [Time]-Dimension enthält [Year], [Quarter], [Month] und [Day]. Diese Seite behandelt jeden Aspekt der Erstellung von Dimensionen in Mondrian 4, von der einfachsten Ein-Tabellen-Dimension bis zu Snowflake-Joins, Zeit-Funktionen, Member-Properties und SQL-Optimierungshinweisen.

Dimensionen und Attribute

Eine Dimension wird mit einem <Dimension>-Element deklariert. Sie hat immer:

  • einen name — den MDX-Namen, der in Abfragen verwendet wird
  • eine table — die Datenbanktabelle (oder den Alias), aus der die Dimension gezogen wird
  • einen key — den Namen des Attributs, das jede Zeile eindeutig identifiziert
Customer:
table: "customer"
key: "Id"
attributes:
- name: "Gender"
- name: "Id"

Jedes <Attribute> innerhalb von <Attributes> wird unabhängig in MDX abfragbar. Mondrian generiert automatisch eine Single-Level-Attribut-Hierarchie für jedes Attribut (siehe Attribut-Hierarchien unten), sodass Sie sofort Attribute in Abfragen verwenden können, ohne explizit <Hierarchy>-Elemente zu definieren.

Dimensions-Schlüssel

Jede Dimension muss ein Schlüsselattribut haben — das Attribut, dessen Werte jede Zeile in der Dimensionstabelle eindeutig identifizieren. Sie deklarieren es mit dem key-Attribut auf <Dimension>, das auf den name eines der Attribute in <Attributes> matchen muss.

Zum Beispiel zeigt in der obigen [Customer]-Dimension key="Id" auf das <Attribute name="Id" column="customer_id"/>. Das Schlüsselattribut wird verwendet, wenn die Dimension über <ForeignKeyLink> mit einer Faktentabelle verbunden wird.

Attribut-Schlüssel und -Name

Der Schlüssel eines Attributs ist die Spalte (oder Spalten), die einen Member eindeutig identifizieren. Standardmäßig ist der Name des Attributs — der String, der den Benutzern angezeigt wird — auch der Schlüssel. Sie können dies überschreiben:

attributes:
- name: "Month"
key:
- "the_year"
- "month"
name_column: "month_name"
order_by_column: "month"

Schlüsselkonzepte:

  • column (oder ein verschachtelter <Key>/<Column>-Block) — die Spalte(n), die den Member identifizieren. Ein zusammengesetzter Schlüssel stellt sicher, dass Member in zwei verschiedenen Jahren, die zufällig denselben Namen teilen (z. B. Q1), als separate Member behandelt werden.
  • nameColumn — die anzuzeigende Spalte. Wenn weggelassen, wird der Schlüssel (letzte Spalte in einem zusammengesetzten Schlüssel) verwendet.
  • orderByColumn — die Spalte, die die Sortierreihenfolge steuert. Wenn weggelassen, werden Member nach Namen sortiert.
  • captionColumn — die Spalte für die Caption, falls anders als der Name.

Attribut-Reihenfolge

Standardmäßig werden Attribute nach ihrem Namen sortiert. Das ist nicht immer das, was Sie wollen. Betrachten Sie das [Month]-Attribut — wenn Monatsnamen als Strings gespeichert sind, gibt die alphabetische Reihenfolge April, August, Dezember… statt Januar, Februar, März…

Beheben Sie dies, indem Sie orderByColumn auf die numerische Monatsspalte setzen:

attributes:
- name: "Month"
key:
- "the_year"
- "month"
name_column: "month_name"
order_by_column: "month"

Mit orderByColumn="month", das auf die numerische 1..12-Spalte zeigt, sortiert Mondrian nach der Zahl, zeigt aber den menschenlesbaren Namen an.

Hierarchien und Levels

Einige Attribute werden natürlich zusammen verwendet. Ein Business-Benutzer, der einen Staat ansieht, möchte ihn oft erweitern, um Städte zu sehen. Beim Betrachten eines Monats möchte er möglicherweise in Quartal oder Jahr rollen. Für solche Kombinationen definieren Sie eine Hierarchie.

Eine Hierarchie ist eine geordnete Liste von Attributen — gröber oben, feiner unten. Jeder Eintrag in der Hierarchie ist ein Level.

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"

Jedes <Level attribute="..."/> referenziert ein Attribut namentlich. Die Attribut-Definitionen erledigen die meiste Arbeit; die Hierarchie ist nur eine Deklaration, welche Attribute Sie in welcher Reihenfolge möchten.

Attribute für die Verwendung in Hierarchien entwerfen

Die Schlüsselregel für Hierarchien: Jedes Attribut muss funktional vom Attribut des Levels darunter abhängig sein. Das bedeutet, dass es für jeden gegebenen Month genau ein Quarter und für jedes gegebene Quarter genau ein Year geben muss.

Eine Year → Month → Week → Day-Hierarchie würde diese Regel verletzen, weil einige Tage in Woche 5 zu Januar und einige zu Februar gehören.

Die praktische Konsequenz ist, dass die meisten Attribute in einer Hierarchie zusammengesetzte Schlüssel brauchen, um die Eltern-Kind-Beziehung zu erfassen. Wenn Ihr Quarter-Attribut nur 4 Member hat (weil Sie vergessen haben, the_year in seinen Schlüssel aufzunehmen), wird die Level-Sequenz 10, 4, 120, 3652 sein — eine nicht-steigende Sequenz, die einen Modellierungsfehler signalisiert.

Reihenfolge und Anzeige von Levels

Das orderByColumn-Attribut auf <Attribute> steuert, wie Member innerhalb eines Levels sortiert werden. Die nameColumn steuert den Anzeigestring. Diese beiden Attribute sind unabhängig: Sie können nach einer numerischen Spalte sortieren und einen menschenlesbaren Namen anzeigen.

Ordinal-Spalten können von jedem Datentyp sein, der in einer ORDER BY-Klausel verwendet werden kann. Die Sortierung ist pro-Eltern gescopt — eine day_in_month-Spalte zirkuliert innerhalb jedes Monats von 1 bis 28–31.

Das type-Attribut auf <Attribute> (Werte: String, Integer, Numeric, Boolean, Date, Time, Timestamp) sagt Mondrian, wie SQL für den Schlüssel dieses Attributs generiert werden soll. Der Standard ist Numeric. Wenn der Schlüssel ein String ist, muss Mondrian es wissen, damit es Werte in einfache Anführungszeichen wickeln kann:

WHERE productSku = '123-455-AA'

„All”- und Default-Member

Standardmäßig enthält jede Hierarchie ein Top-Level namens (All), das einen einzelnen Member namens (All {hierarchyName}) enthält. Dieser Member ist der Eltern aller anderen Member und stellt eine Gesamtsumme dar. Er ist auch der Default-Member — der Member, der verwendet wird, wenn die Hierarchie auf den Abfrageachsen fehlt.

Sie können dieses Verhalten mit Attributen auf <Hierarchy> anpassen:

AttributBeschreibung
hasAllOb das (All)-Level existiert. Standard true.
allMemberNameName des All-Members. Standard "All {hierarchyName}".
allLevelNameName des All-Levels. Standard "(All)".
defaultMemberVollqualifizierter MDX-Name des Default-Members.
<Hierarchy name="Yearly" hasAll="false" defaultMember="[Time].[1997].[Q1].[1]">
...
</Hierarchy>

Wenn hasAll="false", wird der Default-Member der erste Member des ersten Levels — für eine Time-Hierarchie das erste Jahr in den Daten. Dies kann unerwartete Ergebnisse verursachen, wenn diese Hierarchie nicht auf einer Achse ist, also bevorzugen Sie hasAll="true", es sei denn, Sie haben einen spezifischen Grund.

Wenn defaultMember gesetzt ist, kann er sogar ein Calculated Member sein.

Attribut-Hierarchien {#attribut-hierarchien}

MDX kennt keine Attribute — es kennt nur Dimensionen, Hierarchien, Levels und Member. Mondrian überbrückt die Lücke, indem es automatisch eine Single-Level-Hierarchie für jedes Attribut generiert, die Attribut-Hierarchie genannt wird.

Attribut-Hierarchien funktionieren genauso wie manuell deklarierte Hierarchien. Sie lassen Sie ein Dutzend Attribute exponieren und sofort abfragen, ohne <Hierarchy>-Elemente zu schreiben.

Um eine Attribut-Hierarchie zu steuern, verwenden Sie die folgenden Attribute auf <Attribute>:

<Hierarchy>-Attribut<Attribute>-AttributBeschreibung
N/AhasHierarchyOb eine Attribut-Hierarchie generiert wird. Standard: true.
nameN/AIst immer gleich dem Attributnamen.
hasAllhierarchyHasAllOb die Hierarchie ein (All)-Level hat. Standard: true.
allMemberNamehierarchyAllMemberNameName des All-Members.
allMemberCaptionhierarchyAllMemberCaptionCaption des All-Members.
allLevelNamehierarchyAllLevelNameName des All-Levels.
defaultMemberhierarchyDefaultMemberVollqualifizierter MDX-Name des Default-Members.

Attribute vs. Hierarchien

In Mondrian 3 waren Hierarchien aufwendig zu definieren, und die MDX-Syntax war umständlich, wenn eine Dimension mehr als eine Hierarchie hatte. Daher exponierten die meisten Schemas Dimensionen als eine einzige Hierarchie und behandelten einzelne Levels als die Analyseeinheit.

Mondrian 4 fördert einen anderen Ansatz: Mit vielen Attributen entwerfen, Hierarchien nur dort hinzufügen, wo sie nützlich sind.

  • Definieren Sie Attribute für jede Spalte, nach der Sie schneiden möchten.
  • Lassen Sie Benutzer den Cube erkunden.
  • Wenn Sie bemerken, dass bestimmte Kombinationen von Attributen immer zusammen verwendet werden (z. B. Year → Quarter → Month), erstellen Sie eine Hierarchie für diesen Drill-Pfad.
  • Benutzer werden meist weiterhin eigenständige Attribute verwenden.

Eine Feinheit: Einige Attribute haben innerhalb-Eltern- und ohne-Eltern-Varianten. Zum Beispiel ist [Time].[Month] (120 Member über 10 Jahre) anders als [Time].[Month of Year] (12 Member). Das erste lässt Sie Dezember 2012 mit Dezember 2011 vergleichen; das zweite lässt Sie Dezember mit April über alle Jahre vergleichen. Sie brauchen zwei separate Attribute. Eine Namenskonvention wie "X of Parent" hilft Benutzern zu verstehen, welche welche ist.

Schema-Kurzschreibweisen

XML kann ausführlich sein. Mondrian bietet Kurzschreibweisen, um einfache Dinge präzise zu halten.

Attribut als Kurzform für ein Singleton-verschachteltes Element

Wenn ein Attribut einen Einzelspalten-Schlüssel hat, können Sie schreiben:

<Attribute name="A" column="c"/>

statt der längeren Form:

<Attribute name="A">
<Key>
<Column name="c"/>
</Key>
</Attribute>

Wenn ein zusammengesetzter Schlüssel oder ein tabellenübergreifender Spaltenverweis benötigt wird, verwenden Sie die verschachtelte <Key>-Form.

Dasselbe Kurzschreib-Muster gilt über das Schema hinweg:

Eltern-ElementKurzschreibweise-AttributÄquivalentes verschachteltes ElementBeschreibung
<Attribute>keyColumn<Key>Spalte(n), die den Schlüssel dieses Attributs umfassen.
<Attribute>nameColumn<Name>Spalte, die als Member-Name angezeigt wird. Standard ist der Schlüssel.
<Attribute>orderByColumn<OrderBy>Spalte(n), die die Sortierreihenfolge definieren. Standard ist der Schlüssel.
<Attribute>captionColumn<Caption>Spalte, die die Caption bildet. Standard ist der Name.
<Measure>column<Arguments>Spalte(n), die an die SQL-Aggregatfunktion übergeben werden.
<Table>keyColumn<Key>Spalte(n), die den Primärschlüssel der Tabelle bilden.
<Link>foreignKeyColumn<ForeignKey>Spalte(n), die den Fremdschlüssel aus der verweisenden Tabelle eines Links bilden.
<ForeignKeyLink>foreignKeyColumn<ForeignKey>Spalte(n), die die Faktentabelle einer Measure-Gruppe mit einer Dimensionstabelle verbinden.

Vererbtes table-Attribut

Das table-Attribut auf <Dimension>, <Attribute> und <Column> wird vom umschließenden Element vererbt, wenn es nicht explizit gesetzt ist. Dies macht Ein-Tabellen-Dimensionen präzise — deklarieren Sie table einmal auf <Dimension>, und jedes <Attribute> darin erbt es automatisch.

Shared Dimensions

Wenn mehrere Cubes im selben Schema Dimensionen mit derselben Definition verwenden, definieren Sie eine Shared Dimension auf der Schema-Ebene und referenzieren Sie sie aus jedem Cube.

Die Measures-Dimension

Measures werden als Member einer speziellen Dimension namens Measures behandelt. Sie hat eine einzige Hierarchie und ein einziges Level. Weil es nur eine Hierarchie gibt, lässt MDX Sie den Hierarchienamen weglassen:

[Measures].[Unit Sales]

ist die Kurzform für:

[Measures].[Measures].[Unit Sales]

Dieses Design bedeutet, dass Sie den Measure-Kontext in einer Berechnung genauso leicht ändern können wie eine Zeitperiode oder eine Verkaufsregion — es ermöglicht eine größere Formel-Wiederverwendung und macht Zugriffskontrolle einfacher (ein Grant auf einer Zelle ist eine dreidimensionale Koordinate: Cube × Dimension-Slice × Measure).

Stern- und Snowflake-Dimensionen

Stern-Dimensionen

Die bisher gesehenen Dimensionen ziehen alle ihre Spalten aus einer einzelnen Tabelle. Diese werden Stern-Dimensionen genannt, weil sie wie Punkte an einem Stern von der Faktentabelle abstrahlen.

Snowflake-Dimensionen

Eine Snowflake-Dimension umfasst zwei oder mehr zusammenverbundene Dimensionstabellen. Bevor Sie eine definieren, stellen Sie sicher:

  1. Jede Tabelle im Snowflake ist im <PhysicalSchema> deklariert.
  2. Ein <Link>-Element existiert für jeden Join zwischen Tabellen im Snowflake.

Hier ist das product- und product_class-Paar, das zum Aufbau der [Product]-Dimension verwendet wird:

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"

Dann definieren Sie die Dimension und geben table-Overrides auf Attributebene an, wo erforderlich:

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"

Das table-Attribut kaskadiert: <Dimension table="product"> setzt den Standard, <Attribute table="product_class"> überschreibt ihn, und <Column table="product_class"> überschreibt erneut. Mondrian meldet einen Fehler, wenn es keinen Pfad zwischen den Tabellen gibt oder wenn es mehr als einen Pfad gibt.

Zeit-Dimensionen

MDX umfasst zeitbewusste Funktionen — ParallelPeriod, PeriodsToDate, WTD, MTD, QTD, YTD, LastPeriod —, die nur korrekt funktionieren, wenn Mondrian weiß, welche Attribute Zeitperioden darstellen.

Deklarieren Sie eine Zeit-Dimension, indem Sie type="TimeDimension" zu <Dimension> hinzufügen. Markieren Sie dann jedes Attribut mit einem levelType-Wert:

levelType-WertBedeutung
TimeYearsJahr
TimeHalfYearHalbjahr
TimeQuartersQuartal
TimeMonthsMonat
TimeWeeksWoche
TimeDaysTag
TimeHoursStunde
TimeMinutesMinute
TimeSecondsSekunde

Eine vollständige Zeit-Dimension sieht so aus:

<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>

Tier- und Duration-Attribute

Zwei Attributformen werden aus den zugrundeliegenden Spalten berechnet statt direkt aus einer Schlüsselspalte gelesen. Beide sind Saiku-Erweiterungen zu Mondrian 4 (Issue #108): Sie desugaren zu einem dialektspezifischen SQL-Ausdruck, der durch das Calcite-Backend gerendert wird, sodass Sie die gebinneten/abgeleiteten Member ohne Modellierung einer Hilfstabelle oder eines Views bekommen.

Tier (Binning)

Ein <Tier> verwandelt eine numerische Spalte in eine kleine Menge geordneter, benannter Bins — das schema-native Äquivalent zu LookMLs type: tier. Jeder Bin außer dem letzten trägt eine numerische boundary (seine exklusive Obergrenze); eine Zeile übernimmt das Label des ersten Bins, dessen Boundary ihr Wert strikt kleiner als ist. Der letzte Bin lässt boundary weg und erfasst alles bei oder über der letzten Grenze. Member sortieren nach Boundary-Reihenfolge, nicht lexikalisch.

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)

column ist erforderlich; ein optionales table wählt die Quelltabelle, wenn es nicht die eigene (oder Dimensions-) Tabelle des Attributs ist.

Duration

Ein <Duration> berechnet ein numerisches Intervall zwischen zwei Datums-/Timestamp-Spalten in einer festen unit — das Äquivalent zu LookMLs dimension_group: { type: duration }. Die Member sind Zahlen und sortieren numerisch.

attributes:
- name: "Lead Time (months)"
duration:
start_column: "order_date"
end_column: "ship_date"
unit: "MONTH"

startColumn und endColumn sind erforderlich; unit ist eines von DAY (Standard), WEEK, MONTH, QUARTER, YEAR, HOUR, MINUTE, SECOND. Ein optionales table wählt die Quelltabelle.

Member-Properties

Member-Properties hängen zusätzliche Informationen an Member eines Attributs an — Daten, die mit dem Attribut verwandt sind, aber nicht als Schlüssel oder zur Gruppierung verwendet werden. Sie deklarieren sie mit <Property> innerhalb von <Attribute>:

<Attribute name="City" keyColumn="city_id">
<Property attribute="Country"/>
<Property attribute="State"/>
<Property attribute="City Population" name="Population"/>
</Attribute>

Hier gewinnt das [City]-Attribut drei Properties:

  • Country und State erben ihren Namen vom referenzierten Attribut.
  • City Population wird per Attributnamen referenziert, aber als Population über das explizite name-Override exponiert.

Properties werden in Bezug auf andere Attribute in derselben Dimension definiert. Das bedeutet, jede Property hat einen Schlüssel, einen Namen, eine Caption und eine Sortierreihenfolge — wie jedes Attribut. Das referenzierte Attribut muss funktional abhängig vom annotierten Attribut sein. Eine Property auf [Zipcode] auf [City] wäre illegal — eine Stadt kann mehrere Postleitzahlen haben. Aber jede Stadt hat genau einen Staat, ein Land und einen Bevölkerungswert.

Sie können Properties in MDX über:

member.Properties("propertyName")

zugreifen. Zum Beispiel:

SELECT {[Measures].[Store Sales]} ON COLUMNS,
TopCount(
Filter(
[Customer].[City].Members,
[Customer].[City].CurrentMember.Properties("Population") < 10000),
10,
[Measures].[Store Sales]) ON ROWS
FROM [Sales]

Mondrian leitet den Property-Typ vom type-Attribut der <Property>-Definition ab (String, Numeric oder Boolean), wenn der Property-Name ein konstanter String ist. Wenn Sie den Property-Namen dynamisch mit einem Ausdruck bauen, gibt Mondrian einen ungetypten Wert zurück.

Degenerate Dimensions

Eine Degenerate Dimension ist eine, die so einfach ist, dass sie keine eigene Dimensionstabelle rechtfertigt. Betrachten Sie eine payment_method-Spalte (Werte: Credit, Cash, ATM), die direkt in der Faktentabelle sitzt. Eine separate Drei-Zeilen-Lookup-Tabelle nur für diese Werte zu erstellen, fügt einen Join ohne Nutzen hinzu.

Stattdessen deklarieren Sie eine Dimension, ohne ein table anzugeben, und Mondrian liest die Spalten direkt aus der Faktentabelle. In M4 können Sie dies tun, indem Sie das table-Attribut auf <Dimension> weglassen und sicherstellen, dass die column des Attributs in der Faktentabelle existiert:

Payment Method:
key: "Payment Method"
attributes:
- name: "Payment Method"
key_column: "payment_method"

Weil es keinen Join gibt, brauchen Sie keine <ForeignKeyLink>-Fremdschlüsselspalte — die payment_method-Spalte ist bereits in der Faktentabelle. Auch keine <Link>-Elemente sind erforderlich.

Ungefähre Level-Kardinalität

Das approxRowCount-Attribut auf <Attribute> (und auf <Level> innerhalb expliziter Hierarchien) sagt Mondrian ungefähr, wie viele unterschiedliche Member dieses Attribut hat. Diesen Hinweis bereitzustellen kann die Performance erheblich verbessern, indem die Notwendigkeit reduziert wird, dass Mondrian COUNT(DISTINCT ...)-Abfragen zur Bestimmung der Kardinalität ausführt — besonders spürbar bei Verbindung über XMLA.

<Attribute name="Product Name" keyColumn="product_id" approxRowCount="1560"/>

Default-Measure-Attribut

Das defaultMeasure-Attribut auf <Cube> lässt Sie explizit angeben, welches Measure ausgewählt wird, wenn eine Abfrage nicht auf die [Measures]-Dimension verweist. Ohne es wählt Mondrian das erste im Cube deklarierte Measure.

Das Setzen von defaultMeasure ist besonders nützlich, wenn Sie möchten, dass ein Calculated Member der Standard ist, da Calculated Members nach Basis-Measures deklariert werden:

<Cube name="Sales" defaultMeasure="Unit Sales">
...
<CalculatedMember name="Profit" dimension="Measures">
<Formula>[Measures].[Store Sales] - [Measures].[Store Cost]</Formula>
...
</CalculatedMember>
</Cube>

Optimierungen funktionaler Abhängigkeit

Wenn Mondrian SQL generiert, um Dimensions-Member zu füllen, verwendet es GROUP BY, um Zeilen zu deduplizieren. In einigen Schemas können Sie deklarieren, dass bestimmte Spalten funktional abhängig von anderen sind — was redundante GROUP BY-Spalten eliminiert und die Abfrage-Performance verbessert.

Zwei Attribute aktivieren dies:

dependsOnLevelValue auf <Property>

Das Setzen von dependsOnLevelValue="true" auf einer Property sagt Mondrian, dass der Property-Wert für jeden gegebenen Level-Wert konstant ist. Zum Beispiel existiert eine Produktionsstätte in genau einer Stadt und einem Staat, sodass State- und City-Properties funktional abhängig vom ManufacturingPlant-Level sind.

uniqueKeyLevelName auf <Hierarchy>

Das Setzen von uniqueKeyLevelName="Vehicle Identification Number" auf einer Hierarchie sagt Mondrian, dass das benannte Level — zusammen mit allen Levels darüber — als eindeutiger alternativer Schlüssel fungiert. Für jede eindeutige Kombination dieser Level-Werte gibt es genau eine Kombination von Werten für alle Levels darunter.

Beispiel:

<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>

Wenn Mondrian bestätigen kann, dass:

  1. Die Abfrage das Unique-Key-Level einschließt, und
  2. Alle Properties in der Abfrage dependsOnLevelValue="true" haben

…kann es die GROUP BY-Klausel vollständig fallen lassen, was ein substanzieller Performance-Gewinn auf großen Dimensionstabellen ist.

Auf Datenbanken, die nicht-gruppierte Spalten in SELECT zulassen (wie MySQL), kann Mondrian eine teilweise Optimierung sogar ohne uniqueKeyLevelName anwenden — wobei funktional abhängige Properties aus dem GROUP BY weggelassen werden, während die nicht-abhängigen Spalten darin bleiben.


Übernommen aus dem Mondrian-Projekt-Schema-Guide, verfügbar unter der Eclipse Public License v1.0.