[知识体系] 理解物化 Materialization

  [复制链接]
查看120045 | 回复125 | 2021-2-21 19:32:01 | 显示全部楼层 |阅读模式
Materialization,也就是物化,是列式数据库进行查询解析时的一个步骤,了解它何时发生以及如何发生是优化 DAX 非常重要的一项知识。

理解引擎计值流

为了帮助理解什么是物化,先看这个简单的查询:
  1. EVALUATE
  2. ROW (
  3. "Result", COUNTROWS ( SUMMARIZE ( Sales, Sales[ProductKey] ) )
  4. )
复制代码

结果是销售表中产品键的不重复计数。即使我们还没有介绍查询引擎(将在圣经 2.0 版本中介绍),你也可以想象 VertiPaq 是如何执行这个查询的。因为唯一被查询的列是 ProductKey,所以它只能扫描该列,在列的压缩结构中查找所有值。在扫描过程中,它跟踪在位图索引中找到的值,在结束时,它只需要对标记的位进行计数。由于组的并行计算特性,这个查询可以在非常大的表上以很快的速度运行,它唯一需要分配的内存是用于对 ProductKey 进行计数的位图索引


上面的查询在压缩之后的列上运行。换句话说,不需要对列进行解压缩,也不需要重新构建原始表来解析它。这个特性可以优化查询时的内存占用,以减少内存读取。


同样的情况也发生在更复杂的查询中。请看以下代码:
  1. EVALUATE
  2. ROW (
  3.     "Result", CALCULATE (
  4.         COUNTROWS ( Sales ),
  5.         Product[Brand] = "Contoso"
  6.     )
  7. )
复制代码

这一次,我们使用两个不同的表:Sales 和 Product。运行这个查询需要引擎做更多的工作。因为筛选器在产品表上,而要聚合的是销售表,所以不能只扫描单个列。


如果你还不习惯列式数据库,你可能会认为公式将迭代销售表,跟踪与产品的关系,如果产品品牌是 Contoso,则求和时标记为 1,否则标记 0。因此,你可能会想到下面这种类似的算法:
  1. EVALUATE
  2. ROW (
  3.     "Result", SUMX (
  4.         Sales,
  5.         IF (
  6.             RELATED ( Product[Brand] ) = "Contoso",
  7.             1,
  8.             0
  9.         )
  10.     )
  11. )
复制代码

这种算法虽然看上去简单,但它隐藏的复杂性远远超过预期。实际上,如果仔细考虑 VertiPaq 的列式特性,这个查询涉及三个不同的列:


  • Product[Brand]用于筛选产品表。
  • Product[ProductKey]用于跟踪产品表与销售表之间的关系。
  • Sales[ProductKey]用于从销售表一端跟踪关系。


迭代 Sales[ProductKey],每行扫描 Product[ProductKey]检索对应的产品表的行号,最后在 Product[brand]中收集品牌信息,整套操作的开销会非常大,需要对内存进行大量随机读取,从而对性能产生负面影响。实际上,VertiPaq 使用了一种完全不同的算法,针对列式数据库进行了优化。

内部发生了什么?

首先,它扫描 Product[Brand]并检索值为 Contoso 的行号。如下图所示,它扫描 Brand dictionary(步骤 1),检索 Contoso 的编码,最后扫描 segment(步骤 2)搜索 ID = 0 的行号,将索引返回到所找到的行(步骤 3)。


7140211936391.png

扫描后输出品牌等于 Contoso 的行列表


此时,VertiPaq 知道产品表中的哪些行具有给定的品牌。产品表和销售表之间的关系基于 Products[ProductKey],此时 VertiPaq 只知道行号。此外,重要的是记住筛选器将用于销售表,而不是产品表。因此,实际上 VertiPaq 并不需要 Product [ProductKey]的值,它真正需要的是 Sales[ProductKey]值的集合,即销售表中的 ID,而不是产品表中的 ID。


VertiPaq 在内部将关系存储为产品表中的行号和 Sales[ProductKey]中的数据 ID 之间的配对。事实证明,这是将筛选器从产品表的行号移动到销售表中的 ProductKeys 的完美数据结构。VertiPaq 对所选行号执行查找,以确定这些行对应的 Sales[ProductKey]值:


7140211936392.png

VertiPaq 扫描 Product Key 以检索 brand 等于 Contoso 的 ID


最后一步是将筛选器应用于销售表。因为我们已经有了 Sales[ProductKey]的值列表,所以扫描 Sales[ProductKey]列就足以将这个值列表转换为行号,并最终对其进行计数。如果不是计算 COUNTROWS,而是对某列求和,那么 VertiPaq 将执行另一个步骤,将行号转换为列值来执行最后一步。


如你所见,这个过程由简单的表扫描组成,在每个步骤中,你访问单个列。然而,由于列中的数据位于相同的内存区域,VertiPaq 顺序读取内存块并对其执行简单操作,每次输出一小片数据结构在接下来的步骤中使用。
在 VertiPaq 中解析查询的过程和我们预想的有很大区别。一开始,你可能不习惯用列式思维而是按表的结构来考虑问题。VertiPaq 的算法针对列扫描进行了优化;表的概念是列式数据库中被淡化
物化的介入



然而在某些情况下,引擎不能使用这些算法,而是需要恢复到表扫描。例如,下面这个查询:
  1. EVALUATE
  2. ROW (
  3.     "Result", COUNTROWS (
  4.         SUMMARIZE (
  5.             Sales,
  6.             Sales[ProductKey],
  7.             Sales[CustomerKey]
  8.         )
  9.     )
  10. )
复制代码

这个查询看起来非常简单,但简单的背后也暴露了列式数据库的局限性(行数据库也面临相同挑战)。查询返回产品和客户的唯一配对的计数。此查询无法通过分别扫描 ProductKey 和 CustomerKey 来解决。这里惟一的选项是构建一个包含惟一的 ProductKey 和 CustomerKey 键值对的表,最后计算其中的行数。换句话说,这一次 VertiPaq 必须构建一个表,即使只有这两列,它也不能直接在原始存储上执行查询。

物化的定义和总结

构建一个包含部分结果的表,并在稍后扫描该表以计算最终值,称为物化(Materialization)。物化发生在很多查询中,它本身没有好坏之分。这完全取决于被物化的表的大小
物化发生在查询过程中,此时最重要的因素是时间,这意味着公式必须尽可能快的得出结果,所以物化的临时表不会被压缩,因为压缩它们将花费大量时间



值得注意的是,当你从一个表中访问多列时,不会发生物化。这完全取决于你对这些列做了什么。例如,下面这样的查询不需要任何物化,即使它访问两个不同的列:
  1. EVALUATE
  2. ROW (
  3.     "Result", SUMX (
  4.         Sales,
  5.         Sales[Quantity] * Sales[Net Price]
  6.     )
  7. )
复制代码

VertiPaq 在扫描两列时执行乘法然后求和,因此不需要物化带有 Quantity 和 NetPrice 的表。然而,如果表达式变得更加复杂,或者需要进一步处理该表(如前一个示例中需要 COUNTROWS 的情况),则可能需要物化。


在极端情况下,物化可能会使用大量内存(有时甚至超过整个数据库的大小)并生成非常慢的查询。当这种情况发生时,你唯一的做法是重写计算或修改模型,使 VertiPaq 不需要生成物化表来应答。在后面的章节中(2.0 版本),你将看到此技术的一些示例。
回复

使用道具 举报

michael | 2021-4-24 18:22:27 | 显示全部楼层
我了个去,顶了
回复

使用道具 举报

wyfrog | 2021-5-28 08:31:14 | 显示全部楼层
站位支持
回复

使用道具 举报

清新贵族 | 2021-9-24 11:21:30 来自手机 | 显示全部楼层
前排,哇咔咔
回复

使用道具 举报

木马 | 2021-9-24 16:19:51 | 显示全部楼层
加油站加油
回复

使用道具 举报

dgfishman | 2021-10-18 22:30:39 | 显示全部楼层
这套视频很不错!!!!
回复

使用道具 举报

bobby | 2021-11-6 09:11:35 | 显示全部楼层
占坑编辑ing
回复

使用道具 举报

lx319 | 2021-11-22 13:17:10 | 显示全部楼层
鼎力支持!!
回复

使用道具 举报

峰磊 | 2021-11-29 19:23:11 | 显示全部楼层
看帖要回,回帖才健康,在踩踩,楼主辛苦了!
回复

使用道具 举报

Laken | 2021-12-7 07:34:06 来自手机 | 显示全部楼层
谢谢,一直在学习云发教育课程!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则