了解 Power BI 中不同的缓存类型


本文翻译自Nikola Ilic的文章—《Understanding different cache types in Power BI》来源:Medium 你知道Power BI依赖于两种不同的缓存类型吗?在这篇文章中,我们将揭开它们各自的运作方式的神秘面纱.

你有多少次发现自己处于以下情况--当你第一次打开报告时,需要一段时间来渲染,但一旦你从其他报告页面来回访问时,同一页面的渲染速度就会明显加快。

是的,我也经历过这种情况。之所以发生这种情况,是因为Power BI缓存了数据,在首次运行后可以更快地做出反应。

听起来像是很简单的一件事,对吗?但它并不仅是如此,本文将试图解开Power BI中不同缓存类型的神秘面纱。

由于我将提到Power BI的一些内部架构组件,即存储引擎和公式引擎,你还应该了解这两个引擎在数据检索过程中的不同作用。本文的其余部分将假定您了解存储引擎和公式引擎的关键特征。

缓存类型简述

让我们先从高层次的角度解释两种主要的缓存类型,然后我们再深入解释每种类型的细微差别。

Power BI中的视觉对象缓存

让我们从一个非常简单的例子开始。我将在所有的演示中使用一个Contoso数据库样本。

我有一个可视化的簇状柱形图,显示Contoso数据库中存在的每个品牌的总销售金额。还有一个品牌名称的切片器。让我们在Power BI Desktop中打开性能分析器,并选择切片器中的一个值:

正如你可能注意到的,公式引擎生成了一个DAX查询来检索关于Contoso品牌销售数据,而存储引擎需要14ms来实际返回这些数据。由于我们使用的是导入存储模式,而且在Power BI Desktop中,数据被存储在分析服务的本地实例中。

现在让我们把切片器的值改为Litware:

同样,发生的工作流程与前面的情况相同。现在,如果我在切片器中切换回Contoso,会发生什么?

现在事情变得有趣了! 根本就没有DAX查询,而且复制查询选项(使我们能够抓取查询并在DAX Studio中对其进行更详细的分析)是灰色的 这意味着,公式引擎没有生成查询,而这个视觉对象的数据是从缓存中提供的。在这种情况下,我们谈论的是视觉对象缓存。

如果我在切片器中再次选择Litware,同样的情况也会发生。然而,一旦我点击顶部的刷新视觉对象选项...

尽管再次为Contoso检索了数据,但在这种情况下,视觉对象缓存被清除了,公式引擎再次生成了一个DAX查询。

显然,在这个十分基本的例子中,不容易发现这两种情况在性能上的明显差异。但是,在现实中,我们通常会应用更复杂的逻辑,从缓存中检索查询结果通常会比反复运行相同的查询要快得多。

如果我现在从DAX Studio连接到我的Analysis Services本地实例,并打开所有查询,一旦我点击刷新视觉对象,所有的查询将被DAX Studio捕获:

在这里,我将双击第一个查询并在DAX Studio中执行它:

这个包含查询结果的表将被报告缓存起来。而且,每当我们的视觉对象要求相同的结果时,数据可以从缓存中提供。

那么Power BI Service呢

好的,在上面的例子中,我们解释了当使用Power BI Desktop时,Power BI将如何在分析服务的本地实例中缓存查询结果。合理的问题是:一旦我们转移到Power BI Service会发生什么?这个缓存的 "东西 "还能用吗?

答案是--是的! 在这种情况下,它是通过你的网络浏览器完成的。然而,请记住,视觉对象缓存有一个特定的Power BI会话的范围。我们将在后面详细解释这个问题。

Power BI中的数据缓存

数据缓存是Power BI中的另一种缓存类型。与前面的情况不同,缓存发生在单个报告用户的层面上,数据缓存在一个更通用的层面上运作--分析服务的表格模型层面。

如果你做了功课,你可能知道VertiPaq以一种压缩的方式在内存中存储我们的Contoso数据。

那么,当我们要求Power BI计算Contoso品牌的总销售金额时,究竟发生了什么?公式引擎生成并执行一个DAX查询,但随后存储引擎将DAX翻译成一种特殊的类似SQL的语言,称为xmSQL,以便从表格模型中物理地提取数据。

对于每一个xmSQL查询,都有一个特殊的数据结构,称为数据缓存,被存储在内存中。

如果我在DAX Studio中打开服务器计时功能,并运行前面例子中捕获的DAX查询:

正如你可能注意到的,查询结果是从缓存中获取的(我们有一个存储引擎查询,而那一个存储引擎查询是使用缓存的)。这意味着,在现实中,我们并没有真正地查询分析服务模型。为了确认这一点,我将打开DAX Studio中的缓存选项卡,你将在第1行看到,这个查询实际上是从缓存中提供的,而不是从分析服务的内部数据结构中提供的。

注意了! 关于数据缓存需要注意的事项

现在,关于数据缓存,至少有两个重要的考虑因素需要牢记。

首先,它可能会欺骗你,让你认为你的查询正在快速运行,尽管事实可能并非如此。比方说,你正在对一个性能不佳的查询进行故障排除,你利用DAX Studio来深入了解后台发生的事情。你第一次运行该查询,它需要2000毫秒才能返回结果。

然后你应用一些小的变化,再次运行查询--现在它在100毫秒内完成了渲染--好耶! 你开始思考:"嗯,为什么每个人都说DAX很难?我只是重新排列了我的代码中的行数,它的工作速度快了20倍......"

是的,没错! 第二天早上,一个报告用户再次抱怨说,同一个报告的视觉对象渲染得很慢。

你可能忘了在运行DAX计算的 "改进 "版本之前清除数据缓存。

即使在这个极其简单的计算中,使用来自缓存的结果集的方案也比查询分析服务的内部数据结构的方案快了近4倍(请注意第1行,其中包含Internal作为一个子类)。

第二,由于数据缓存驻留在内存中,这意味着它的资源确实有限。简单地说,并不是所有的查询都能在分析服务中被缓存起来!这取决于查询的数据量!根据查询所检索的数据量,可能会发生只有一部分(或没有)存储引擎的查询可以从缓存中检索。

让我给你看看这在现实中是怎样的。我在我的Power BI报告中又添加了一些成分。比方说,我想计算一下我们在每一年有多少个不同的订单。我创建了一个简单的DAX度量值来计算它:

Distinct Orders = DISTINCTCOUNT(FactOnlineSales[SalesOrderNumber])

接下来,我想把这个值与前一年的值进行比较,所以我将去创建另一个度量来计算前一年的不同订单数量:

Distinct Orders PY = CALCULATE(
[Distinct Orders],
SAMEPERIODLASTYEAR(DimDate[Datekey])
)

让我们切换到DAX Studio,检查生成的查询,以填充这个视觉对象的数据:

由于我在运行这个查询之前没有清除数据缓存,10个存储引擎查询都是从缓存中检索出来的!7毫秒内返回了全部结果!

我现在清除缓存,重新运行同样的查询:

之前是7毫秒,现在是1秒多!这就是为什么我告诉你,在运行相同的查询之前清除数据缓存是非常重要的。

现在让我们检查一下,如果我们在范围中包括个别日期,而不是年份,会发生什么:

在不清除缓存的情况下,这个查询需要16秒以上的时间才能返回结果!

简单解释一下这里发生的事情:当查询执行时,存储引擎检索数据,并将中间的查询结果具体化在一个叫做数据缓存的特殊结构中。在最终的结果集回到报告之前,这个数据缓存最终被公式引擎所消耗。现在,根据许多不同的情况,有时所有必要的数据都可以在一个数据缓存中具体化,但有时可能发生的情况是,有太多的数据需要扫描和具体化,所以存储引擎创建了多个数据缓存。

在我们的例子中,我们可以看到,每一个查询都非常快--只有几毫秒--但数量很多。准确地说:2195次查询。

现在,如果没有那么多数据需要物化,会发生什么?我们可以 "帮助 "引擎再次利用数据缓存功能吗?

我将在我的报告中添加一个日期切片器,只包括2010年1月1日之后的日期:

让我们看看DAX Studio服务器计时现在显示什么:

显然,查询的运行速度更快,因为引擎需要处理的数据缓存数量更少。但是,我们仍然无法利用数据缓存。

现在让我们只包括2010年10月1日之后的日期,并在DAX Studio中检查查询结果:

这一次,我们击中的是缓存,差异是巨大的!这个查询只花了134ms就得到了结果。

总而言之,从数据缓存的角度来看,你的查询有多少数据被扫描和物化是极其重要的。

结论

缓存查询结果是关键的性能优化概念之一,并不完全与Power BI和表格模型有关,而是普遍存在。

当我们研究Power BI的缓存类型时,你应该注意到两种不同的缓存:

视觉对象缓存(或报告缓存)--数据被缓存在特定的Power BI会话范围内,尽管如此,如果我们谈论的是本地机器上的Power BI Desktop会话,或Power BI Service中的会话。
数据缓存--数据在分析服务实例的范围内进行缓存,无论打开的Power BI会话的数量如何。

转载请注明出处!


如果您想深入学习微软Power BI,欢迎登录网易云课堂试听学习我们的“从Excel到Power BI数据分析可视化”系列课程。或者关注我们的公众号(PowerPivot工坊)后猛戳”在线学习”。



长按下方二维码关注“Power Pivot工坊”获取更多微软Power BI、PowerPivot相关文章、资讯,欢迎小伙伴儿们转发分享~


Power Pivot工坊