1

我有一个收集性能指标并将它们存储在数据集市中的应用程序。然后,我使用 Mondrian 对数据进行分析和临时探索。我每天收集大约 5e6 行,METRIC 表的总大小约为 300M 行。

我们根据与 SLA 的指标比较为我们的数据“着色”。颜色正好有 5 个不同的值。例如,当我们执行简单的 MDX 查询以获取特定日期范围(例如 1 天)的数据颜色分布时,我们会看到如下查询:

2014-06-11 23:17:08,042 调试 [sql] - 223: SqlTupleReader.readTuples [[Color].[Color]]: 执行 sql [select "METRIC"."COLOR" as "c0" from "METRIC"" METRIC”组按“METRIC”。“COLOR”按“METRIC”排序。“COLOR”ASC NULLS LAST] 2014-06-11 23:17:58,747 DEBUG [sql] - 223: , exec 50704 ms

为了提高性能,数据集市包含小时和天级别的聚合表,并且两个聚合表都包含 COLOR 列。

我知道蒙德里安非常依赖底层数据库的性能,但真的没有办法调整它。我可以在 COLOR 上创建索引(因为索引的完整扫描将比表的完整扫描稍微快一些),但是在 300M 行表上创建具有 5 个不同值的索引似乎很愚蠢。day 聚合表有大约 500K 行,并且对这个表执行几乎相同的查询会明显更快,但 Mondrian 似乎总是针对这些维度查询使用基本事实表。

我的问题是,有没有办法避免这个查询?如果我无法避免,是否可以让 Mondrian 使用聚合表进行此类查询?我已经在这个维度/层次结构的单个级别中指定了 approxRowCount,并且消除了类似的查询来获取值的计数。我还没有深入了解 Mondrian 的来源,以确定是否有可能使用聚合表,或者我是否有一些配置阻止了它。

编辑澄清:

我可能没有很好地提出我的问题——让我试着澄清一下。我的 MDX 查询类似于:

select [Color].[Color].Members on columns,
       {[Measures].[Metric Value], [Measures].[Count]} on rows
from [Metric]
where [Time].[2014].[June].[11]

我可以看看这个并手写一个 SQL 查询来回答这个查询

select COLOR, avg(VALUE), sum(FACT_COUNT) 
from AGG_DAY_METRIC
where YEAR = 2014 
  and MONTH = 6
  and DAY_OF_MONTH = 11
group by COLOR

数据库在大约 100 毫秒内扫描大约 4K 行来回答这个查询。Mondrian 需要几分钟来回答查询,因为它执行了几个不直接回答 MDX 查询的查询,而是获取有关维度的信息。在上述情况下,数据库必须扫描 300M 行,用时 50 秒,才能返回有 5 种可能的颜色。如果颜色在正常维度表中,则只有 5 行,但在退化维度中,可能有数百万行。

所以我的问题是:

a)有没有办法告诉蒙德里安退化维度的值并避免这些查询?

b) 有没有办法让蒙德里安从聚合表中回答这些查询?

4

3 回答 3

1

这个问题得到了解决,不是通过修改 Mondrian 模式或应用程序中的任何内容,而是通过修改数据库。本例中的数据库是 Oracle,我们能够创建启用查询重写的物化视图。

物化视图是根据 Mondrian 发出的确切查询创建的。由于颜色值不会非常频繁地更改(在我们的例子中几乎从不),因此物化视图每天会完全刷新一次。

在这种情况下,查询从几分钟到几毫秒。如果您面临这样的问题并且您的数据库是 Oracle,那么这是加快低基数退化维度的元组解析的好方法。

于 2014-09-11T22:42:01.253 回答
0

如果不了解更多有关您的架构的信息,很难给出任何具体的指示,但在我看来,您必须确保必须将具有某些颜色(计数)的行数标记为聚合度量(CountMax Number)。

请注意,这些聚合不是连续计算的(我认为这对于支持数据存储来说会很重,而且 Mondrian 不会在内存中为传入的事实保留一个流动的集合)。

可以指定聚合在特定时间(每晚、每小时...)运行/重建。这会使 Mondrian 有点不适合实时分析,但您应该能够对历史数据进行几乎即时的查询。

于 2014-06-13T18:24:20.177 回答
0

如果您的维度在 300M 事实表中有 5 个不同的值,则它不应该是退化维度。它应该在一个单独的维度表中。仅当其基数接近完整的事实表行数时才应使用退化维度,这使得单独的表毫无意义,因为不会显着节省存储空间,并且加入维度会导致读取大量数据;

如果您将颜色放在单独的暗表上,任何“读取元组”查询将在几毫秒内返回结果,您的问题就解决了。

但是,更重要的是,蒙德里安应该能够从 agg 表中选择暗淡的值。除非您在多维数据集中有不同计数的聚合器,在这种情况下您会遇到棘手的情况(除非有一个聚合表与您需要的详细程度完全匹配,否则 Mondrian 很可能会扫描事实表)。

您还应该将此退化维度的 highCardinality 属性设置为 True。即使只有 5 个不同的值,highCardinality=false 也会告诉 Mondrian 扫描整个维度以填充成员列表是安全的。将其设置为 true 会停止此扫描。

您还应该向该列添加索引。向事实表中的每个键和退化维度列添加索引总是一个好主意。使用索引,数据库应该比 SQL 查询更快地回答。

最后,您有一个 300M 行的事实表。您使用的是什么 DBMS?它是面向列的数据库吗?如果没有,您应该尝试将它们作为数据存储的可能替代方案。对于类似蒙德里安的查询,面向列的 DB 比面向行的 DB 具有显着的性能提升。那里有一些不错的选择,您应该试驾它们。

于 2014-06-14T15:49:01.507 回答