我有一个应用程序,它收集性能指标并将它们存储在datamart中。然后我使用Mondrian来启用数据的分析和临时探索。我每天收集大约5e6行,METRIC表的总大小约为300M行。
我们"颜色"我们的数据基于与SLA的指标比较。颜色正好有5个不同的值。当我们进行简单的MDX查询以获取特定日期范围(例如1天)的数据的颜色分布时,我们会看到如下查询:
2014-06-11 23:17:08,042 DEBUG [sql] - 223:SqlTupleReader.readTuples [[颜色]。[颜色]]:执行sql [select" METRIC"。" COLOR" as" c0" 来自" METRIC" "度量"按" METRIC"。" COLOR"订购 "度量"" COLOR" ASC NULLS LAST] 2014-06-11 23:17:58,747 DEBUG [sql] - 223:,exec 50704 ms
为了提高性能,datamart包括小时和日级别的聚合表,两个聚合表都包含COLOR列。
我知道Mondrian非常依赖于底层的数据库性能,但实际上没有办法调整它。我可以在COLOR上创建一个索引(因为索引的完整扫描将比表的完整扫描略快),但在300M行表上创建一个具有5个不同值的索引似乎很愚蠢。日聚合表有大约500K行,并且对这个表执行几乎相同的查询会明显更快,但Mondrian似乎总是转到这些维查询的基本事实表。
我的问题是,有没有办法避免这种查询?如果我无法避免它,是否可以让Mondrian使用聚合表进行此类查询?我在此维度/层次结构的单个级别中指定了approxRowCount,并且消除了类似的查询以获取值的计数。我还没有挖掘蒙德里安的来源,而是确定是否有可能使用聚合表,或者我的部分是否存在阻止它的配置。
编辑澄清:
我可能没有很好地提出我的问题 - 让我试着澄清一下。我的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
数据库在大约100ms扫描大约4K行时回答此查询。蒙德里安需要几分钟才能回答 查询,因为它会执行多个不直接回答MDX查询的查询,而是获取有关该查询的信息 尺寸。在上面的例子中,数据库必须扫描300M行,花费50秒,以返回有5个可能的行 颜色。如果颜色在正常维度表中,则只有5行,但在简并维度中可以有100行 数百万行。
所以我的问题是:
a)有没有办法告诉蒙德里安退化维度的值并避免这些查询?
b)有没有办法让Mondrian从聚合表中回答这些查询?
答案 0 :(得分:1)
此问题已解决,不是通过修改Mondrian架构或应用程序中的任何内容,而是修改数据库。在这种情况下,数据库是Oracle,我们能够创建一个启用了查询重写的物化视图。
物化视图是根据Mondrian发出的确切查询创建的。由于颜色值不会经常变化(在我们的情况下几乎从不),因此物化视图每天都会进行一次完全刷新。
在这种情况下,查询从花费分钟到毫秒。如果您遇到类似这样的问题并且您的数据库是Oracle,那么这是一种加速具有低基数的退化维度的元组分辨率的好方法。
答案 1 :(得分:0)
在不了解您的架构的情况下很难给出任何具体指示,但在我看来,您必须确保必须将具有特定颜色(计数)的行数标记为聚合度量({{ 1}}或Count
)。
请注意,这些聚合不是连续计算的(我认为支持数据存储会很重,而且Mondrian不会在内存中保留一个流动的集合来处理传入的事实。)
可以指定聚合在特定时间(每晚,每小时......)运行/重建。这会使蒙德里安有点不适合进行实时分析,但你应该可以对历史数据进行几乎即时的查询。
答案 2 :(得分:0)
如果您的维度在300M事实表中有5个不同的值,则它不应该是简并维度。它应该在一个单独的维度表中。如果它的基数接近完整的事实表行数,则只能使用退化维度,使单独的表无意义,因为没有显着的存储节省并且加入维度会导致大量数据被读取;
如果你把颜色放在一个单独的昏暗桌子上,那么任何"阅读元组"查询将在几毫秒内返回结果,您的问题就解决了。
然而,更多的问题是,Mondrian应该能够从agg表中选择昏暗的值。除非你在多维数据集中有明确计数的聚合器,否则你处于一个棘手的情况下(除非有一个与你需要的详细程度完全匹配的聚合表,Mondrian很可能会扫描这个事实表)。
您还应将此简并维度的highCardinality属性设置为True。即使只有5个不同的值,具有highCardinality = false告诉Mondrian,扫描整个维度以填充成员列表是安全的。将其设置为true会停止此扫描。
您还应该为此列添加索引。将索引添加到事实表中的每个键和退化维度列始终是一个好主意。使用索引,DB应该比SQL查询快得多。
最后,您有一个300M行事实表。您使用的DBMS是什么?它是面向列的DB吗?如果没有,您应该尝试将它们作为数据存储的替代方案。面向列的DB与面向行的DB相比,对于类似Mondrian的查询具有显着的性能提升。有一些很好的选择,你应该试驾它们。