TotalSales = SUM(Sales[Sales])
RegionalSales = CALCULATE([TotalSales], USERELATIONSHIP(Region[RegionID], Sales[RegionID]))
RegionalSalesDirect = CALCULATE(SUM(Sales[Sales]), USERELATIONSHIP(Region[RegionID], Sales[RegionID]))
请注意 RegionalSales 度量值如何引用 TotalSales 度量值,而 RegionalSalesDirect 度量值不引用。 相反,RegionalSalesDirect 度量值使用表达式 SUM(Sales[Sales])
,它是 TotalSales 度量值的表达式。
结果的差异非常细微。 当 Power BI 评估 RegionalSales 度量值时,它会将 Region 表中的筛选器同时应用于 Sales 表和 Date 表。 因此,筛选器还会从 Date 表传播到 Sales 表。 相比之下,当 Power BI 评估 RegionalSalesDirect 度量值时,它只会将筛选器从 Region 表传播到 Sales 表。 RegionalSales 度量值和 RegionalSalesDirect 度量值返回的结果可能不同,即使表达式在语义上是等效的。
每当将 CALCULATE
函数与作为远程源组中度量值的表达式一起使用时,请全面测试计算结果。
跨源组关系方案 2
假设跨源组关系具有高基数关系列。
在此方案中,Date 表与 Sales 表在 DateKey 列上相关。 DateKey 列的数据类型为整数,存储使用 yyyymmdd 格式的整数。 这些表属于不同的源组。 此外,这是一种高基数关系,因为 Date 表中的最早日期是 1900 年 1 月 1 日,最晚日期是 2100 年 12 月 31 日,因此表中总共有 73,414 行(1900-2100 时间跨度内的每个日期一行)。
有两种情况值得关注。
首先,使用 Date 表列作为筛选器时,筛选器传播将筛选 Sales 表的 DateKey 列以评估度量值。 按单个年份(如 2022 年)进行筛选时,DAX 查询将包含一个筛选表达式,例如 Sales[DateKey] IN { 20220101, 20220102, …20221231 }
。 当筛选器表达式中的值数较大或筛选器值为长字符串时,查询的文本大小可能会变得非常大。 Power BI 生成长查询和数据源运行查询的成本很高。
其次,使用 Date 表列(如 Year、Quarter 或 Month)作为分组列时,会生成包含年、季度或月的所有唯一组合以及 DateKey 列值的筛选器。 查询的字符串大小(包含分组列和关系列的筛选器)可能会变得非常大。 当分组列数和/或联接列(DateKey 列)的基数很大时,尤其如此。
若要解决任何性能问题,可以:
将 Date 表添加到数据源,从而导致单个源组模型(这意味着它不再是复合模型)。
提高关系的粒度。 例如,可以将 MonthKey 列添加到这两个表中,并在这些列上创建关系。 但是,通过提高关系的粒度,你将失去报告每日销售活动的能力(除非使用 Sales 表中的 DateKey 列)。
跨源组关系方案 3
假设跨源组关系中的表之间没有匹配值。
在此方案中,源组 B 中的 Date 表与该源组中的 Sales 表以及源组 A 中的 Target 表有关系。与 Year 列相关的 Date 表中的所有关系都是一对多关系。 Sales 表包含存储销售额的 SalesAmount 列,而 Target 表包含存储目标金额的 TargetAmount 列。
Date 表存储 2021 年和 2022 年。 Sales 表存储 2021 年 (100) 和 2022 年 (200) 的销售额,而 Target 表存储 2021 年 (100)、2022 年 (200) 和 2023 年 (300)(未来一年)的目标金额。
当 Power BI 表视觉对象通过对 Date 表中的 Year 列进行分组并对 SalesAmount 和 TargetAmount 列求和来查询复合模型时,它不会显示 2023 年的目标金额。 这是因为跨源组关系是一种有限的关系,因此它使用 INNER JOIN
语义,这消除了两端没有匹配值的行。 但是,它将生成正确的总目标金额 (600),因为 Date 表筛选器不适用于其计算。
如果 Date 表与 Target 表之间的关系是源组内部关系(假设 Target 表属于源组 B),则视觉对象将包含一个(空白)年,以显示 2023 年(和任何其他不匹配年份)的目标金额。
若要避免错误报告,请确保当维度表和事实数据表位于不同的源组中时,关系列中存在匹配的值。
有关有限关系的详细信息,请参阅关系评估。
将计算列和计算组添加到复合模型时,应考虑特定的限制。
添加到从关系数据库(如 Microsoft SQL Server)中获取数据的 DirectQuery 表的计算列,仅限于一次对单个行进行操作的表达式。 这些表达式不能使用 DAX 迭代器函数(如 SUMX
)或筛选器上下文修改函数(如 CALCULATE
)。
无法添加依赖于链式表格模型的计算列或计算表。
远程 DirectQuery 表上的计算列表达式仅限于行内计算。 但是,可以创作此类表达式,但在视觉对象中使用时会导致错误。 例如,如果使用表达式 [Product Sales] / SUM (DimProduct[ProductSales])
将计算列添加到名为 DimProduct 的远程 DirectQuery 表,则可以成功将表达式保存在模型中。 但是,在视觉对象中使用时会导致错误,因为它违反了行内评估限制。
相比之下,添加到远程 DirectQuery 表的计算列(该表是一个表格模型,可以是 Power BI 数据集,也可以是 Analysis Services 模型)更加灵活。 在这种情况下,允许所有 DAX 函数,因为将在源表格模型中计算表达式。
许多表达式要求 Power BI 将计算列具体化,然后再将其用作组或筛选器,或将其聚合。 在大型表中具体化计算列时,根据计算列所依赖的列的基数,CPU 和内存的成本可能很高。 在这种情况下,建议将这些计算列添加到源模型。
将计算列添加到复合模型时,请务必测试所有模型计算。 上游计算可能无法正常工作,因为它们没有考虑它们对筛选器上下文的影响。
如果计算组存在于连接到 Power BI 数据集或 Analysis Services 模型的源组中,则 Power BI 可能会返回意外结果。 有关详细信息,请参阅计算组、查询和度量值评估。
应始终通过采用星型架构设计来优化 Power BI 模型。
有关详细信息,请参阅了解星型架构和 Power BI 的重要性。
请务必创建独立于事实数据表的维度表,以便 Power BI 可以正确解释联接并生成高效的查询计划。 虽然本指南适用于任何 Power BI 模型,但尤其适用于你识别将成为复合模型的源组的模型。 它将允许在下游模型中更简单、更高效地集成其他表。
尽可能避免在一个源组中使用与不同源组中的事实数据表相关的维度表。 这是因为具有源组内部关系比跨源组关系更好,尤其是对于高基数关系列。 如前所述,跨源组关系依赖于在关系列中具有匹配的值,否则可能会在报表视觉对象中显示意外结果。
行级别安全性
如果模型包括用户定义的聚合、导入表上的计算列或计算表,请确保正确设置并测试任何行级安全 (RLS)。
如果复合模型连接到其他表格模型,则 RLS 规则仅应用于定义它们的源组(本地模型)。 它们不会应用于其他源组(远程模型)。 此外,不能在来自另一个源组的表上定义 RLS 规则,也不能在与另一个源组有关系的本地表上定义 RLS 规则。
在某些情况下,可以通过设计优化的报表布局来提高复合模型的性能。
单个源组视觉对象
尽可能创建使用单个源组中的字段的视觉对象。 这是因为,当从单个源组检索结果时,视觉对象生成的查询性能会更好。 请考虑创建并排放置的两个视觉对象,用于从两个不同的源组检索数据。
使用同步切片器
在某些情况下,可以设置同步切片器以避免在模型中创建跨源组关系。 它允许你直观地合并源组,从而可以更好地执行。
假设模型有两个源组。 每个源组都有一个产品维度表,用于筛选经销商和 Internet 销售。
在此方案中,源组 A 包含与 ResellerSales 表相关的 Product 表。 源组 B 包含与 InternetSales 表相关的 Product2 表。 没有任何跨源组关系。
在报表中,添加一个切片器,该切片器使用 Product 表的 Color 列筛选页面。 默认情况下,切片器会筛选 ResellerSales 表,但不筛选 InternetSales 表。 然后,使用 Product2 表的 Color 列添加隐藏的切片器。 通过设置相同的组名(在同步切片器“高级选项”中找到),应用于可见切片器的筛选器将自动传播到隐藏的切片器。
虽然使用同步切片器可以避免创建跨源组关系,但会增加模型设计的复杂性。 请务必让其他用户了解你设计具有重复维度表的模型的原因。 通过隐藏不希望其他用户使用的维度表来避免混淆。 还可以向隐藏表添加说明文本,以记录其用途。
有关详细信息,请参阅同步单独的切片器。
下面是一些其他指南,可帮助你设计和维护复合模型。
性能和规模:如果报表以前实时连接到 Power BI 数据集或 Analysis Services 模型,则 Power BI 服务可以在报表之间重复使用视觉对象缓存。 将实时连接转换为创建本地 DirectQuery 模型后,报表将不再受益于这些缓存。 因此,可能会遇到性能降低甚至刷新失败的情况。 此外,Power BI 服务的工作负荷也会增加,这可能需要纵向扩展容量或在其他容量之间分配工作负荷。 有关数据刷新和缓存的详细信息,请参阅 Power BI 中的数据刷新。
重命名:不建议重命名复合模型使用的数据集,也不建议重命名其工作区。 这是因为复合模型通过使用工作区和数据集名称(而不是其内部唯一标识符)连接到 Power BI 数据集。 重命名数据集或工作区可能会中断复合模型使用的连接。
治理:不建议将单一事实版本模型作为复合模型。 这是因为它将依赖于其他数据源或模型,如果更新这些数据源或模型,可能会导致复合模型中断。 而是建议将企业语义模型发布为单一事实版本。 将此模型视为可靠的基础。 然后,其他数据建模者可以创建复合模型,用于扩展基础模型以创建专用模型。
数据世系:在发布复合模型更改之前,请使用数据世系和数据集影响分析功能。 这些功能在 Power BI 服务中提供,它们可以帮助你了解数据集的相关性和使用方式。 务必了解,你无法对显示在世系视图中但实际位于另一工作区的外部数据集执行影响分析。 若要对外部数据集执行影响分析,你需要导航到源工作区。
架构更新:在对上游数据源进行架构更改时,应在 Power BI Desktop 中刷新复合模型。 然后,需要将模型重新发布到 Power BI 服务。 请务必全面测试计算和依赖报表。
有关本文的详细信息,请查看以下资源。
在 Power BI Desktop 中使用复合模型
Power BI Desktop 中的模型关系
Power BI Desktop 中的 DirectQuery 模型
在 Power BI Desktop 中使用 DirectQuery
使用适用于 Power BI 数据集和 Analysis Services 的 DirectQuery
Power BI Desktop 中的存储模式
用户定义的聚合
是否有任何问题? 尝试咨询 Power BI 社区
建议? 提出改进 Power BI 的想法