用户定义的聚合

Power BI 中的聚合可以提高大型 DirectQuery 语义模型的查询性能。 通过使用聚合,可以在聚合级别内存中缓存数据。 可以在数据模型中手动配置 Power BI 中的聚合,如本文所述。 对于高级订阅,可以在模型设置中启用 自动聚合 功能以自动创建它们。

创建聚合表

根据数据源类型,您可以在数据源上将聚合表创建为表、视图或使用本机查询。 为了获得最佳性能,请将聚合表创建为 Power Query 中创建的导入表。 使用 Power BI Desktop 中的“管理聚合”对话框为包含汇总、详细信息表和详细信息列属性的聚合列定义聚合。

维度数据源(如数据仓库和数据市场)可以使用 基于关系的聚合。 基于 Hadoop 的大型数据源通常 基于 GroupBy 列进行基本聚合。 本文介绍每种数据源类型的典型 Power BI 数据建模差异。

管理聚合

在任何 Power BI Desktop 视图 的数据 窗格中,右键单击聚合表,然后选择“ 管理聚合”。

选择“管理聚合”的屏幕截图。

管理聚合 ”对话框显示表中每一列的行,可在其中指定聚合行为。 在以下示例中, 对 Sales 详细信息表的查询在内部重定向到 Sales Agg 聚合表。

屏幕截图显示了“管理聚合”对话框。

在此基于关系的聚合示例中,GroupBy 条目是可选的。 除了 DISTINCTCOUNT 之外,它们不会影响聚合行为,主要用于可读性。 如果没有 GroupBy 条目,聚合仍会根据关系执行。 此行为不同于本文后面的 大数据示例 ,其中需要 GroupBy 条目。

验证

“管理聚合”对话框强制实施验证:

  • “详细信息列”的数据类型必须与聚合列具有相同的数据类型,“计数”和“计数表行汇总”函数除外。 计数和计数表行功能仅适用于整数聚合列,并不需要特定的数据类型。
  • 不允许包含三个或多个表的链式聚合。 例如,表 A 上的聚合不能引用一个包含引用表 C 的聚合的表 B
  • 不允许重复聚合,其中两个条目使用相同的 汇总 函数并引用相同的 详细信息表详细信息列
  • 详细信息表必须使用 DirectQuery 存储模式,而不是导入。
  • 不支持基于非活动关系中使用的外键列进行分组,也不支持依赖 USERELATIONSHIP 函数来完成聚合计算。 或者,可以使用 TREATAS 函数而不是 USERELATIONSHIP。 使用 TREATAS 时,请确保表之间没有活动关系。 将 TREATAS 用于此配置时,仍可命中聚合。
  • 在基于 GroupBy 列的聚合中,可以使用聚合表之间的关系,但在 Power BI Desktop 中不支持创作聚合表之间的关系。 如有必要,可以通过 XML for Analysis(XMLA)终结点使用第三方工具或脚本解决方案在聚合表之间创建关系。

通过禁用下拉列表值并在工具提示中显示解释性文本来强制实施大多数验证。

通过工具提示显示的验证

聚合表处于隐藏状态

对模型具有只读访问权限的用户无法查询聚合表。 当与 行级别安全性 (RLS) 一起使用时,只读访问可避免安全问题。 消费者和查询主要关注详细信息表,而不是聚合表,也不需要了解聚合表。

因此,聚合表在 报表 视图中处于隐藏状态。 如果表尚未隐藏,则选择“全部应用”时,“管理聚合”对话框会将其设置为隐藏。

存储模式

聚合功能适用于表级存储模式。 Power BI 表可以使用 DirectQuery导入双重 存储模式。 DirectQuery 直接将查询发送到后端,而Import 则将数据导入到内存中进行缓存,并对缓存的数据发送查询。 所有 Power BI 导入和非多维 DirectQuery 数据源都使用聚合。

若要将聚合表的存储模式设置为“导入”以加快查询速度,请在 Power BI Desktop 模型 视图中选择聚合表。 在 “属性 ”窗格中,展开“ 高级”,在 “存储”模式下下拉列表选择,然后选择“ 导入”。 将存储模式设置为“导入”后,无法再次更改它。

选择存储模式的屏幕截图。

有关表存储模式的详细信息,请参阅 Power BI Desktop 中的管理存储模式

聚合的 RLS

若要正确处理聚合,RLS 表达式应同时筛选聚合表和详细信息表。

在以下示例中, Geography 表中的 RLS 表达式适用于聚合,因为 Geography 位于 Sales 表和 Sales Agg 表的关系筛选端。 使用聚合表的查询和不使用聚合表的查询都成功应用了 RLS。

在聚合中的成功 RLS

Product 表上的 RLS 表达式仅筛选详细信息 Sales 表,而不是聚合的 Sales Agg 表。 由于聚合表是详细信息表中数据的另一种表示形式,因此如果无法应用 RLS 筛选器,则从聚合表中应答查询将不安全。 不建议仅筛选详细信息表,因为来自此角色的用户查询不会受益于聚合命中。

不允许使用仅筛选Sales Agg聚合表而不是Sales详细表的RLS表达式。

不允许仅在聚合表上使用 RLS

对于 基于 GroupBy 列的聚合,应用于详细信息表的 RLS 表达式可以筛选聚合表,因为聚合表中的所有 GroupBy 列都由详细信息表覆盖。 另一方面,聚合表上的 RLS 筛选器无法筛选详细信息表,因此不允许它。

基于关系的聚合

维度模型通常 使用基于关系的聚合。 数据仓库和数据集市中的 Power BI 模型类似于星型和雪花型架构,维度表和事实数据表之间存在着关系。

在以下示例中,模型从单个数据源获取数据。 表使用 DirectQuery 存储模式。 Sales 事实数据表包含数十亿行。 将 Sales 的存储模式设置为“导入”进行缓存将消耗大量内存和资源开销。

模型中的明细表

而是创建 Sales Agg 聚合表。 在 Sales Agg 表中,行数等于按 CustomerKeyDateKeyProductSubcategoryKey 分组后的 SalesAmount 的总和。 Sales Agg 表的粒度更细化,相较于 Sales,因此,它可能包含数百万行而不是数十亿行,使其更易于管理。

如果以下维度表被最常用于具有高业务价值的查询,那么可以通过一对多多对一关系来筛选Sales Agg

  • 地理
  • 客户
  • 日期
  • 产品子类别
  • 产品类别

下图显示了此模型。

模型中的聚合表

下表显示了 Sales Agg 表的聚合。

Sales Agg 表的聚合

注释

与任何表一样, Sales Agg 表具有以各种方式加载的灵活性。 可以使用 ETL 或 ELT 进程或使用表的 M 表达式 在源数据库中执行聚合。 聚合表可以使用导入存储模式,配合或不配合 语义模型的增量刷新。 或者,它可以使用 DirectQuery,并使用 列存储索引针对快速查询进行优化。 这种灵活性使平衡的体系结构能够分散查询负载以避免瓶颈。

将聚合 Sales Agg 表的存储模式更改为 “导入 ”将打开一个对话框,指出可以将相关的维度表设置为 “双”存储模式。

存储模式对话框

将相关维度表设置为“双重模式”可以使它们根据子查询扮演 Import 或 DirectQuery 的角色。 在示例中:

  • 从导入模式 Sales Agg 表中聚合指标,并按相关 Dual 表的属性进行分组的查询将结果从内存缓存中返回。
  • 聚合 DirectQuery Sales 表中的指标的查询,以及按相关双表的属性分组的查询,以 DirectQuery 模式返回结果。 查询逻辑(包括 GroupBy 操作)将传递到源数据库。

有关双存储模式的详细信息,请参阅 Power BI Desktop 中的“管理存储模式”。

常规关系与有限关系

基于关系的聚合命中需要常规关系。

常规关系包括以下存储模式组合,其中两个表都来自单个源:

面表 表位于 1
双重 双重
进口 导入或双重
DirectQuery DirectQuery 或 Dual

仅当两个表都设置为 Import 时 ,跨源 关系是正则。 多对多关系始终有限。

有关不依赖于关系的 跨源 聚合结果的信息,请参阅 基于 GroupBy 列的聚合

基于关系的聚合查询示例

以下查询使用聚合,因为 Date 表中的列具有适合使用聚合的粒度。 SalesAmount 列使用 Sum 聚合。

成功的基于关系的聚合查询

以下查询不使用聚合。 尽管请求 SalesAmount 的总和,但查询正按 Product 表中的一列执行 GroupBy 操作,而该列的粒度不支持使用此类聚合。 如果观察模型中的关系,则产品子类别可以具有多个 Product 行。 查询无法确定要聚合到哪个产品。 在这种情况下,查询将还原为 DirectQuery,并将 SQL 查询提交到数据源。

无法使用聚合的查询

聚合不仅仅用于执行简单求和的计算。 复杂的计算也可以受益。 从概念上讲,复杂计算被分解为每个 SUM、MIN、MAX 和 COUNT 函数的子查询。 将评估每个子查询,以确定它是否可以使用聚合。 由于查询计划优化,此逻辑并非在所有情况下适用,但一般情况下应是有效的。 以下示例使用聚合:

复杂聚合查询

COUNTROWS 函数可以从聚合中受益。 以下查询使用聚合,因为为 Sales 表定义了 Count 表行 聚合。

COUNTROWS 聚合查询

AVERAGE 函数可以从聚合中受益。 以下查询使用聚合,因为 AVERAGE 在内部被转换为由 SUM 和 COUNT 相除的形式。 由于 UnitPrice 列为 SUM 和 COUNT 定义了聚合,因此将使用这些聚合。

平均值聚合查询

在某些情况下,DISTINCTCOUNT 函数可以从聚合中受益。 以下查询使用聚合,因为 CustomerKey 有一个 GroupBy 条目,它维护聚合表中 CustomerKey 的区别。 此方法可能仍会达到性能阈值,其中超过 2 到 500 万个非重复值可能会影响查询性能。 在拥有数十亿行的明细表中,但列内存在200到500万个不同值的场景中,这可能会很有用。 在这种情况下,DISTINCTCOUNT 的执行速度可能快于扫描具有数十亿行的表,即使该表缓存到内存中也是如此。

DISTINCTCOUNT 聚合查询

数据分析表达式 (DAX) 时间智能函数可识别聚合。 以下查询使用聚合,因为 DATESYTD 函数生成 CalendarDay 值的表,并且该聚合表的粒度适合于 Date 表中的分组列。 这是计算函数的表值筛选器的示例,该函数可用于聚合。

SUMMARIZECOLUMNS 聚合查询

基于 GroupBy 列的聚合

基于 Hadoop 的大数据模型具有不同于维度模型的特征。 为了避免大型表之间的联接,大数据模型通常不使用关系,而是将维度属性非规范化为事实数据表。 可以使用 基于 GroupBy 列的聚合解锁此类大数据模型进行交互式分析。

下表包含要聚合的 Movement 数值列。 所有其他列都是用于分组的属性。 该表包含 IoT 数据和大量行。 存储模式为 DirectQuery。 由于数据量巨大,对整个模型进行汇总的数据源查询速度较慢。

IoT 表

若要对此模型启用交互式分析,请添加一个聚合表,该表按大多数属性进行分组,但不包括经度和纬度等高基数属性。 此方法显著减少了行数,并且内存缓存也可以轻松容纳。

司机活动汇总表

“管理聚合”对话框中定义驱动程序活动 Agg 表的聚合映射。

管理驱动程序活动 Agg 表的聚合对话框

在基于 GroupBy 列的聚合中, GroupBy 条目不是可选的。 如果没有它们,聚合不会被命中。 此行为不同于使用基于关系的聚合,其中 GroupBy 条目是可选的。

下表显示了 驱动程序活动 Agg 表的聚合。

驱动程序活动 Agg 聚合表

将聚合 驱动程序活动 Agg 表的存储模式设置为“导入”。

GroupBy 聚合查询示例

以下查询使用聚合,因为聚合表涵盖 “活动日期 ”列。 COUNTROWS 函数使用 已计数的表行 聚合。

成功的 GroupBy 聚合查询

尤其是对于包含事实数据表中的筛选器属性的模型,最好使用 Count 表行 聚合。 在用户未显式请求时,Power BI 可以使用“COUNTROWS”函数向模型提交查询。 例如,筛选器对话框显示每个值的行计数。

“筛选”对话框

组合聚合技术

可以结合关系和 GroupBy 列技术用于聚合操作。 基于关系的聚合可能需要将非规范化维度表拆分为多个表。 如果此要求对于某些维度表而言成本高昂或不切实际,则可以复制这些维度的聚合表中的必要属性,并为其他维度使用关系。

例如,以下模型复制 Sales Agg 表中的月份季度学期年份Sales AggDate 表之间没有关系,但与 CustomerProduct Subcategory 之间有关系。 Sales Agg 的存储模式为 Import。

组合聚合技术

下表显示了 Sales Agg 表的“管理聚合”对话框中设置的条目。 必须使用Date作为详细信息表中的 GroupBy 条目,以便在按 Date属性分组的查询中使用聚合。 与前面的示例一样,CustomerKeyProductSubcategoryKeyGroupBy 条目不会影响聚合使用,除非 DISTINCTCOUNT,因为存在关系。

Sales Agg 聚合表的条目

合并聚合查询示例

以下查询使用聚合,因为聚合表涵盖 CalendarMonth,并且可以通过一对多关系访问 CategoryName 。 查询对 SalesAmount 使用 SUM 聚合。

针对聚合的查询示例

以下查询不使用聚合,因为聚合表不包括 CalendarDay

屏幕截图显示包含 CalendarDay 的查询文本。

以下时间智能查询不使用聚合,因为 DATEYTD 函数会生成 CalendarDay 值的表,并且聚合表不包括 CalendarDay

屏幕截图显示包含 DATEYTD 函数的查询的文本。

聚合优先级

聚合优先级允许单个子查询考虑多个聚合表。

以下示例是包含多个源 的复合模型

  • Driver Activity DirectQuery 表包含来自大型数据系统的一万亿多行 IoT 数据。 它提供深入查询,用于查看在受控过滤条件下的单个 IoT 数据读取。
  • 驱动程序活动 Agg 表是 DirectQuery 模式下的中间聚合表。 它包含在 Azure Synapse Analytics(前称 SQL 数据仓库)中的超过 10 亿行数据,并在数据源中通过列存储索引进行了优化。
  • Driver Activity Agg2 导入表的粒度较高,因为按组的属性数量较少且基数较低。 行数可能低至数千,因此可以轻松存入内存缓存中。 这些属性被一个高级的执行仪表板使用,因此引用它们的查询应尽可能快速。

注释

仅当聚合表来自 SQL Server、Azure SQL 或 Azure Synapse Analytics(前 SQL 数据仓库)源时,才支持使用与详细信息表不同的数据源的 DirectQuery 聚合表。

此模型的内存占用量相对较小,但它解锁了一个巨大的模型。 它表示一个平衡的体系结构,因为它将查询负载分散到体系结构的组件之间,并基于其优势利用它们。

用于激活大型模型的小型占用空间模型的表

驱动程序活动 Agg2“托管聚合”对话框将“优先级”字段设置为 10,高于“驱动程序活动 Agg”。 优先级较高的设置意味着使用聚合的查询首先考虑 驱动程序活动 Agg2 。 未在驱动程序活动 Agg2粒度范围内的子查询可以考虑使用驱动程序活动 Agg。 任何一个聚合表都无法回答的详细信息查询可以定向到 驱动程序活动

“详细信息表 ”列中指定的表是 “驱动程序活动”,而不是 “驱动程序活动 Agg”,因为不允许链接聚合。

屏幕截图显示了“管理聚合”对话框,其中已调出“优先级”。

下表显示了 驱动程序活动 Agg2 表的聚合。

驱动程序活动 Agg2 聚合表

检测查询命中还是错过聚合

SQL Profiler 可以检测查询是否来自内存中缓存存储引擎,或者 DirectQuery 是否将其推送到数据源。 可以使用同一进程来检测是否正在使用聚合。 有关详细信息,请参阅 命中或错过缓存的查询

SQL Profiler 还提供 Query Processing\Aggregate Table Rewrite Query 扩展事件。

以下 JSON 代码片段显示了使用聚合时事件输出的示例。

  • matchingResult 显示子查询使用聚合。
  • dataRequest 显示子查询使用的 GroupBy 列和聚合列。
  • 映射 显示映射到的聚合表中的列。

使用聚合时事件的输出

使缓存保持同步

合并 DirectQuery、导入和双存储模式的聚合可以返回不同的数据,除非内存中缓存与源数据保持同步。 例如,查询执行不会尝试通过筛选 DirectQuery 结果来掩盖数据问题,以匹配缓存的值。 您可能需要在问题的源头处理这些问题。 性能优化绝不会损害满足业务需求的能力。 需要相应地了解数据流和设计。

注意事项和限制

  • 聚合不支持 动态 M 查询参数

  • 自 2022 年 8 月起,由于功能更改,Power BI 会忽略启用了单一登录(SSO)的导入模式聚合表,因为存在潜在的安全风险。 若要确保聚合的查询性能最佳,请禁用这些数据源的 SSO。

Community

Power BI 拥有充满活力的社区,其中 MVP、BI 专业人员和同行在讨论组、视频、博客等中分享专业知识。 了解聚合时,请务必查看以下资源: