用户定义的聚合

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

创建聚合表

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

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

管理聚合

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

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

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

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

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

验证

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

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

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

通过工具提示显示的验证

聚合表处于隐藏状态

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

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

存储模式

聚合功能与表级存储模式交互。 Power BI 表可以使用 DirectQuery导入双重 存储模式。 DirectQuery 直接查询后端,而导入会在内存中缓存数据,并将查询发送到缓存的数据。 所有 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 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 表中聚合指标,并根据相关的双表中的属性进行分组。
  • 可以在 DirectQuery 模式下返回从 DirectQuery Sales 表聚合指标的查询,并按属性(s)对相关双表进行分组。 查询逻辑(包括 GroupBy 操作)将传递到源数据库。

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

常规关系与有限关系

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

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

面表 表位于 1
双重 双重
进口 导入或双重
DirectQuery(直接查询) DirectQuery 或 Dual

只有在两个表都设置为“导入”时,才会将跨源关系视为常规关系。 多对多关系始终被视为有限。

有关不依赖于关系的 跨源 聚合结果的信息,请参阅 基于 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 列的聚合解锁此类大数据模型进行交互式分析。

下表包含要聚合的 移动 数值列。 所有其他列都是用于分组的属性。 该表包含 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 表的“管理聚合”对话框中设置的条目。 GroupBy 条目,其中Date是详细表,是强制性的,以便命中按Date属性分组的查询的聚合。 与前面的示例一样,CustomerKeyProductSubcategoryKeyGroupBy 条目不会影响聚合命中(DISTINCTCOUNT 除外),因为存在关系。

Sales Agg 聚合表的条目

合并聚合查询示例

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

针对聚合的查询示例

以下查询不会命中聚合,因为聚合表不涵盖 CalendarDay

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

以下时间智能查询不会命中聚合,因为 DATESYTD 函数会生成 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。

社区

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