Dimensiones, atributos y jerarquías
Una dimensión es una agrupación de atributos relacionados — los ejes por los que segmenta en una consulta. La dimensión [Customer] podría contener [Gender], [City] y [Country]; la dimensión [Time] contiene [Year], [Quarter], [Month] y [Day]. Esta página cubre cada aspecto de la creación de dimensiones en Mondrian 4, desde la dimensión de una sola tabla más simple hasta los joins copo de nieve, funciones temporales, propiedades de miembro y hints de optimización SQL.
Dimensiones y atributos
Una dimensión se declara con un elemento <Dimension>. Siempre tiene:
- un
name— el nombre MDX usado en consultas - una
table— la tabla de base de datos (o alias) de la que se extrae la dimensión - una
key— el nombre del atributo que identifica de forma única cada fila
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>Cada <Attribute> dentro de <Attributes> se vuelve consultable independientemente en MDX. Mondrian genera automáticamente una jerarquía de atributo de un solo nivel para cada atributo (consulte Jerarquías de atributo debajo), así que puede empezar a usar atributos en consultas sin definir explícitamente ningún elemento <Hierarchy>.
Clave de dimensión
Cada dimensión debe tener un atributo clave — el atributo cuyos valores identifican de forma única cada fila en la tabla de dimensión. La declara con el atributo key en <Dimension>, que debe coincidir con el name de uno de los atributos en <Attributes>.
Por ejemplo, en la dimensión [Customer] de arriba, key="Id" apunta a <Attribute name="Id" column="customer_id"/>. El atributo clave se usa cuando se enlaza la dimensión a una tabla de hechos mediante <ForeignKeyLink>.
Clave y nombre de atributo
La clave de un atributo es la columna (o columnas) que identifican de forma única a un miembro. Por defecto, el nombre del atributo — la cadena mostrada a los usuarios — es también la clave. Puede sobrescribirlo:
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>Conceptos clave:
column(o un bloque<Key>/<Column>anidado) — la(s) columna(s) que identifican al miembro. Una clave compuesta asegura que los miembros en dos años diferentes que casualmente comparten el mismo nombre (por ejemplo,Q1) se traten como miembros separados.nameColumn— la columna a mostrar. Si se omite, se usa la clave (última columna en una clave compuesta).orderByColumn— la columna que controla el orden de clasificación. Si se omite, los miembros se ordenan por nombre.captionColumn— la columna para la leyenda, si es diferente del nombre.
Orden de atributo
Por defecto, los atributos se ordenan por su nombre. Esto no siempre es lo que quiere. Considere el atributo [Month] — si los nombres de mes se almacenan como cadenas, el orden alfabético da April, August, December… en lugar de January, February, March…
Arregle esto definiendo orderByColumn a la columna numérica del mes:
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>Con orderByColumn="month" apuntando a la columna numérica 1..12, Mondrian ordena por el número pero muestra el nombre legible.
Jerarquías y niveles
Algunos atributos se usan naturalmente juntos. Un usuario de negocio que mira un estado a menudo quiere expandirlo para ver ciudades. Mirando un mes, podría querer hacer rollup en trimestre o año. Para tales combinaciones, define una jerarquía.
Una jerarquía es una lista ordenada de atributos — más gruesos arriba, más finos abajo. Cada entrada en la jerarquía es un nivel.
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>Cada <Level attribute="..."/> referencia un atributo por nombre. Las definiciones de atributo hacen la mayor parte del trabajo; la jerarquía es solo una declaración de qué atributos quiere y en qué orden.
Diseñar atributos para usar en jerarquías
La regla clave para las jerarquías: cada atributo debe ser funcionalmente dependiente del atributo del nivel debajo de él. Eso significa que debe haber exactamente un Quarter para cualquier Month dado, y exactamente un Year para cualquier Quarter dado.
Una jerarquía Year → Month → Week → Day violaría esta regla, porque algunos días en la Semana 5 pertenecen a enero y otros a febrero.
La consecuencia práctica es que la mayoría de los atributos en una jerarquía necesitan claves compuestas para capturar la relación padre-hijo. Si su atributo Quarter tiene solo 4 miembros (porque olvidó incluir the_year en su clave), la secuencia de niveles será 10, 4, 120, 3652 — una secuencia no creciente que señala un error de modelado.
Orden y visualización de niveles
El atributo orderByColumn en <Attribute> controla cómo se ordenan los miembros dentro de un nivel. nameColumn controla la cadena para mostrar. Estos dos atributos son independientes: puede ordenar por una columna numérica y mostrar una columna de nombre legible.
Las columnas ordinales pueden ser de cualquier tipo de dato que pueda usarse en una cláusula ORDER BY. El orden está acotado por padre — una columna day_in_month cicla de 1 a 28–31 dentro de cada mes.
El atributo type en <Attribute> (valores: String, Integer, Numeric, Boolean, Date, Time, Timestamp) le dice a Mondrian cómo generar SQL para la clave de ese atributo. El valor por defecto es Numeric. Si la clave es una cadena, Mondrian necesita saberlo para que pueda envolver los valores en comillas simples:
WHERE productSku = '123-455-AA'Miembros ‘All’ y por defecto
Por defecto, cada jerarquía contiene un nivel superior llamado (All), que contiene un único miembro llamado (All {hierarchyName}). Este miembro es el padre de todos los demás miembros y representa un total general. También es el miembro por defecto — el miembro usado cuando la jerarquía está ausente de los ejes de la consulta.
Puede personalizar este comportamiento con atributos en <Hierarchy>:
| Atributo | Descripción |
|---|---|
hasAll | Si existe el nivel (All). Por defecto true. |
allMemberName | Nombre del miembro all. Por defecto "All {hierarchyName}". |
allLevelName | Nombre del nivel all. Por defecto "(All)". |
defaultMember | Nombre MDX completamente cualificado del miembro por defecto. |
<Hierarchy name="Yearly" hasAll="false" defaultMember="[Time].[1997].[Q1].[1]"> ...</Hierarchy>Cuando hasAll="false", el miembro por defecto se convierte en el primer miembro del primer nivel — para una jerarquía Time, el primer año en los datos. Esto puede causar resultados inesperados cuando esa jerarquía no está en un eje, así que prefiera hasAll="true" a menos que tenga una razón específica.
Cuando se define defaultMember, puede incluso ser un miembro calculado.
Jerarquías de atributo
MDX no sabe sobre atributos — solo sabe sobre dimensiones, jerarquías, niveles y miembros. Mondrian cubre el hueco generando automáticamente una jerarquía de un solo nivel para cada atributo, llamada una jerarquía de atributo.
Las jerarquías de atributo funcionan exactamente como las jerarquías declaradas manualmente. Le permiten exponer una docena de atributos y empezar a consultarlos enseguida, sin escribir ningún elemento <Hierarchy>.
Para controlar una jerarquía de atributo, use los siguientes atributos en <Attribute>:
Atributo de <Hierarchy> | Atributo de <Attribute> | Descripción |
|---|---|---|
| N/A | hasHierarchy | Si se genera una jerarquía de atributo. Por defecto: true. |
name | N/A | Siempre igual al nombre del atributo. |
hasAll | hierarchyHasAll | Si la jerarquía tiene un nivel (All). Por defecto: true. |
allMemberName | hierarchyAllMemberName | Nombre del miembro all. |
allMemberCaption | hierarchyAllMemberCaption | Leyenda del miembro all. |
allLevelName | hierarchyAllLevelName | Nombre del nivel all. |
defaultMember | hierarchyDefaultMember | Nombre MDX completamente cualificado del miembro por defecto. |
Atributos frente a jerarquías
En Mondrian 3, las jerarquías eran verbosas de definir y la sintaxis MDX era torpe cuando una dimensión tenía más de una jerarquía. Como resultado, la mayoría de los schemas exponían las dimensiones como una única jerarquía y trataban los niveles individuales como la unidad de análisis.
Mondrian 4 fomenta un enfoque diferente: diseñe con muchos atributos, añada jerarquías solo donde sean útiles.
- Defina atributos para cada columna por la que quiera segmentar.
- Deje que los usuarios exploren el cubo.
- Cuando note que ciertas combinaciones de atributos se usan siempre juntas (por ejemplo, Year → Quarter → Month), cree una jerarquía para esa ruta de drill.
- Los usuarios seguirán usando atributos independientes la mayor parte del tiempo.
Un matiz: algunos atributos tienen variantes dentro del padre y sin padre. Por ejemplo, [Time].[Month] (120 miembros sobre 10 años) es diferente de [Time].[Month of Year] (12 miembros). El primero le permite comparar diciembre de 2012 con diciembre de 2011; el segundo le permite comparar diciembre con abril entre todos los años. Necesita dos atributos separados. Una convención de nombres como "X of Parent" ayuda a los usuarios a entender cuál es cuál.
Atajos del schema
XML puede ser verboso. Mondrian proporciona atajos para mantener concisas las cosas simples.
Atributo como abreviatura de un elemento anidado singleton
Cuando un atributo tiene una clave de una sola columna, puede escribir:
<Attribute name="A" column="c"/>en lugar de la forma más larga:
<Attribute name="A"> <Key> <Column name="c"/> </Key></Attribute>Cuando se necesita una clave compuesta o una referencia a columna cross-tabla, use la forma anidada <Key>.
El mismo patrón de atajo aplica en todo el schema:
| Elemento padre | Atributo abreviado | Elemento anidado equivalente | Descripción |
|---|---|---|---|
<Attribute> | keyColumn | <Key> | Columna(s) que componen la clave de este atributo. |
<Attribute> | nameColumn | <Name> | Columna mostrada como el nombre del miembro. Por defecto la clave. |
<Attribute> | orderByColumn | <OrderBy> | Columna(s) que definen el orden de clasificación. Por defecto la clave. |
<Attribute> | captionColumn | <Caption> | Columna que forma la leyenda. Por defecto el nombre. |
<Measure> | column | <Arguments> | Columna(s) pasadas a la función agregada SQL. |
<Table> | keyColumn | <Key> | Columna(s) que forman la clave primaria de la tabla. |
<Link> | foreignKeyColumn | <ForeignKey> | Columna(s) que forman la clave foránea desde la tabla referente del enlace. |
<ForeignKeyLink> | foreignKeyColumn | <ForeignKey> | Columna(s) que enlazan la tabla de hechos de un grupo de medidas a una tabla de dimensión. |
Atributo table heredado
El atributo table en <Dimension>, <Attribute> y <Column> se hereda del elemento envolvente cuando no se define explícitamente. Esto hace concisas las dimensiones de una sola tabla — declare table una vez en <Dimension> y cada <Attribute> dentro lo hereda automáticamente.
Dimensiones compartidas
Si varios cubos en el mismo schema usan dimensiones con la misma definición, defina una dimensión compartida a nivel del schema y referénciela desde cada cubo.
La dimensión Measures
Las medidas se tratan como miembros de una dimensión especial llamada Measures. Tiene una única jerarquía y un único nivel. Como solo hay una jerarquía, MDX le permite omitir el nombre de la jerarquía:
[Measures].[Unit Sales]es una abreviatura de:
[Measures].[Measures].[Unit Sales]Este diseño significa que puede cambiar el contexto de medida en un cálculo tan fácilmente como cambia un período temporal o una región de ventas — permite mayor reutilización de fórmulas y hace más simple el control de acceso (un grant en una celda es una coordenada tridimensional: cubo × porción de dimensión × medida).
Dimensiones estrella y copo de nieve
Dimensiones estrella
Las dimensiones vistas hasta ahora extraen todas sus columnas de una sola tabla. Estas se llaman dimensiones estrella porque irradian de la tabla de hechos como puntos de una estrella.
Dimensiones copo de nieve
Una dimensión copo de nieve abarca dos o más tablas de dimensión unidas. Antes de definir una, asegúrese de que:
- Cada tabla en el copo de nieve se declara en el
<PhysicalSchema>. - Existe un elemento
<Link>para cada join entre tablas en el copo de nieve.
Aquí está el par product y product_class usado para construir la dimensión [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"/>Luego define la dimensión, especificando sobrescrituras de table a nivel de atributo donde sea necesario:
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>El atributo table se cascada: <Dimension table="product"> define el por defecto, <Attribute table="product_class"> lo sobrescribe, y <Column table="product_class"> lo sobrescribe de nuevo. Mondrian reportará un error si no hay ruta entre las tablas, o si hay más de una ruta.
Dimensiones temporales
MDX incluye funciones conscientes del tiempo — ParallelPeriod, PeriodsToDate, WTD, MTD, QTD, YTD, LastPeriod — que solo funcionan correctamente cuando Mondrian sabe qué atributos representan períodos de tiempo.
Declare una dimensión temporal añadiendo type="TimeDimension" a <Dimension>. Luego marque cada atributo con un valor de levelType:
Valor de levelType | Significado |
|---|---|
TimeYears | Año |
TimeHalfYear | Medio año |
TimeQuarters | Trimestre |
TimeMonths | Mes |
TimeWeeks | Semana |
TimeDays | Día |
TimeHours | Hora |
TimeMinutes | Minuto |
TimeSeconds | Segundo |
Una dimensión temporal completa tiene este aspecto:
<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>Atributos tier y duration
Dos formas de atributo se computan de las columnas subyacentes en lugar de leerse directamente de una columna clave. Ambas son extensiones Saiku a Mondrian 4 (issue #108): se desazucan en una expresión SQL por dialecto renderizada a través del backend Calcite, así que obtiene los miembros agrupados/derivados sin modelar una tabla auxiliar o una vista.
Tier (binning)
Un <Tier> convierte una columna numérica en un pequeño conjunto de bins ordenados y nombrados — el equivalente nativo del schema del type: tier de LookML. Cada bin excepto el último lleva un boundary numérico (su límite superior exclusivo); una fila toma la etiqueta del primer bin cuyo boundary sea estrictamente mayor que su valor. El bin final omite boundary y captura todo lo igual o superior al último límite. Los miembros se ordenan por orden de boundary, no léxicamente.
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 es requerido; un table opcional selecciona la tabla de origen cuando no es la propia tabla del atributo (o de la dimensión).
Duration
Un <Duration> computa un intervalo numérico entre dos columnas date/timestamp en una unit fija — el equivalente del dimension_group: { type: duration } de LookML. Los miembros son números y se ordenan numéricamente.
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 y endColumn son requeridos; unit es uno de DAY (el predeterminado), WEEK, MONTH, QUARTER, YEAR, HOUR, MINUTE, SECOND. Un table opcional selecciona la tabla de origen.
Propiedades de miembro
Las propiedades de miembro adjuntan información extra a los miembros de un atributo — datos que están relacionados con el atributo pero no se usan como clave o para agrupar. Las declara usando <Property> dentro de <Attribute>:
<Attribute name="City" keyColumn="city_id"> <Property attribute="Country"/> <Property attribute="State"/> <Property attribute="City Population" name="Population"/></Attribute>Aquí, el atributo [City] gana tres propiedades:
CountryyStateheredan su nombre del atributo referenciado.City Populationse referencia por nombre de atributo pero se expone comoPopulationmediante la sobrescritura explícita dename.
Las propiedades se definen en términos de otros atributos en la misma dimensión. Esto significa que cada propiedad tiene una clave, un nombre, una leyenda y un orden de clasificación — igual que cualquier atributo. El atributo referenciado debe ser funcionalmente dependiente del atributo que se está anotando. Una propiedad basada en [Zipcode] en [City] sería ilegal — una ciudad puede tener varios códigos postales. Pero cada ciudad tiene exactamente un estado, un país y un valor de población.
Puede acceder a propiedades en MDX mediante:
member.Properties("propertyName")Por ejemplo:
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 infiere el tipo de propiedad del atributo type de la definición <Property> (String, Numeric o Boolean) cuando el nombre de la propiedad es una cadena constante. Si construye el nombre de la propiedad dinámicamente con una expresión, Mondrian devuelve un valor sin tipo.
Dimensiones degeneradas
Una dimensión degenerada es una tan simple que no justifica su propia tabla de dimensión. Considere una columna payment_method (valores: Credit, Cash, ATM) directamente en la tabla de hechos. Crear una tabla de búsqueda separada de tres filas solo para estos valores añade un join sin beneficio.
En su lugar, declare una dimensión sin especificar una table, y Mondrian lee las columnas de la tabla de hechos directamente. En M4 puede hacer esto omitiendo el atributo table en <Dimension> y asegurando que la column del atributo existe en la tabla de hechos:
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>Como no hay join, no necesita una columna de clave foránea <ForeignKeyLink> — la columna payment_method ya está en la tabla de hechos. Tampoco se necesitan elementos <Link>.
Cardinalidad de nivel aproximada
El atributo approxRowCount en <Attribute> (y en <Level> dentro de jerarquías explícitas) le dice a Mondrian aproximadamente cuántos miembros distintos tiene este atributo. Proporcionar este hint puede mejorar significativamente el rendimiento al reducir la necesidad de que Mondrian ejecute consultas COUNT(DISTINCT ...) para determinar la cardinalidad — particularmente notable al conectar mediante XMLA.
<Attribute name="Product Name" keyColumn="product_id" approxRowCount="1560"/>Atributo de medida por defecto
El atributo defaultMeasure en <Cube> le permite especificar explícitamente qué medida se selecciona cuando una consulta no referencia la dimensión [Measures]. Sin él, Mondrian elige la primera medida declarada en el cubo.
Definir defaultMeasure es especialmente útil cuando quiere que un miembro calculado sea el por defecto, ya que los miembros calculados se declaran tras las medidas base:
<Cube name="Sales" defaultMeasure="Unit Sales"> ... <CalculatedMember name="Profit" dimension="Measures"> <Formula>[Measures].[Store Sales] - [Measures].[Store Cost]</Formula> ... </CalculatedMember></Cube>Optimizaciones de dependencia funcional
Cuando Mondrian genera SQL para poblar miembros de dimensión, usa GROUP BY para deduplicar filas. En algunos schemas puede declarar que ciertas columnas son funcionalmente dependientes de otras — eliminando columnas redundantes en GROUP BY y mejorando el rendimiento de la consulta.
Dos atributos habilitan esto:
dependsOnLevelValue en <Property>
Definir dependsOnLevelValue="true" en una propiedad le dice a Mondrian que el valor de la propiedad es constante para cualquier valor de nivel dado. Por ejemplo, una planta de fabricación existe en exactamente una ciudad y un estado, así que las propiedades State y City son funcionalmente dependientes del nivel ManufacturingPlant.
uniqueKeyLevelName en <Hierarchy>
Definir uniqueKeyLevelName="Vehicle Identification Number" en una jerarquía le dice a Mondrian que el nivel nombrado — junto con todos los niveles por encima de él — actúa como una clave alternativa única. Para cualquier combinación única de esos valores de nivel, hay exactamente una combinación de valores para todos los niveles debajo.
Ejemplo:
<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>Cuando Mondrian puede confirmar que:
- La consulta incluye el nivel de clave única, y
- Todas las propiedades en la consulta tienen
dependsOnLevelValue="true"
…puede descartar la cláusula GROUP BY por completo, lo que es una mejora sustancial de rendimiento en tablas de dimensión grandes.
En bases de datos que permiten columnas no agrupadas en SELECT (como MySQL), Mondrian puede aplicar una optimización parcial incluso sin un uniqueKeyLevelName — dejando las propiedades funcionalmente dependientes fuera del GROUP BY mientras mantiene las columnas no dependientes en él.
Adaptado de la guía del schema del proyecto Mondrian, disponible bajo la Eclipse Public License v1.0.