Performance “性能提示”;每个A";MDX查询?(特别是SSAS)

Performance “性能提示”;每个A";MDX查询?(特别是SSAS),performance,ssas,mdx,olap,Performance,Ssas,Mdx,Olap,“给我每个A前5个B”的典型MDX示例如下所示: -- return top 5 clients for each firm select [Measures].[Amount] on columns, NON EMPTY generate( [Firms].[Firm Name].Children, crossjoin( [Firms].[Firm Name].CurrentMember, TopCount([Clients].[Client N

“给我每个A前5个B”的典型MDX示例如下所示:

-- return top 5 clients for each firm
select
  [Measures].[Amount] on columns,
  NON EMPTY generate(
    [Firms].[Firm Name].Children,
    crossjoin(
      [Firms].[Firm Name].CurrentMember,
      TopCount([Clients].[Client Name].Children, 5, [Measures].[Amount])
    )
  )
  on rows
from [FirmsAndClients]
我正在原型化一个UI,它可以执行许多“前5位”类型的查询,因此我正在寻找任何加快查询速度的技巧,特别是当交叉连接(a,B)的度量值大部分为空时

在这个特定的案例中,x个客户机很大(n=5000 x n=20000,或多或少),而且比较稀疏,我能够通过在交叉连接中用过滤器(不是ISEmpty)替换非空的,将速度提高大约100倍:

-- return top 5 clients for each firm
select
  [Measures].[Amount] on columns,
  generate(
    [Firms].[Firm Name].Children,
    crossjoin(
      [Firms].[Firm Name].CurrentMember,
      TopCount(
        filter([Clients].[Client Name].Children, NOT IsEmpty([Measures].[Amount]))
               5,
               [Measures].[Amount])
    )
  )
  on rows
from [FirmsAndClients]
我希望通过运行类似的查询来预热SSAS缓存,从而进一步提高性能,但我发现上面的查询(即带有“过滤器”的查询)在运行热缓存和冷缓存时同样慢。通过使用Sql Profiler,我发现了部分原因:虽然SSAS正在缓存基础多维数据集数据的一部分,但它似乎不会缓存整个查询的结果,也不会缓存由generate或crossjoin创建的中间集。因此,每次我重复查询时,它都必须重做generate、crossjoin和topcount。即使每个topcount似乎需要1ms或更短的时间,但当迭代数千家公司时,这些毫秒加起来

在MDX级别、多维数据集级别或Sql Server调优级别,有关于我可以做什么的提示吗?在SQL世界中,我可以通过在我想要排序的列上创建索引获得一些好处。不过,据我所知,OLAP没有这样的功能


可以想象,这是一个更一般的问题,即当您想要加速涉及复杂排序和筛选的MDX查询时,该怎么做(这显然不适合SSAS缓存系统)。

我在SSAS 2008上玩了更多,根据经验,我为这些查询制定了两个速度原则:

  • 空元组过滤可以有所帮助,但并不总是如此:正如我在最初的帖子中提到的,在将两个稀疏集连接在一起之前而不是之后过滤空元组可以将速度提高一个数量级。(我所说的“稀疏”是指当跨越两个度量值时,大多数度量值都是空的。)但是,如果您事先知道要跨越的MDX集不是稀疏的,TopCount(非空)优化可能会适度降低速度。
    • 注意:如果您确实使用空元组过滤作为性能优化,那么过滤的最佳位置似乎是在调用TopCount之前(即嵌套在内部)
    • 注意:在我最初的帖子中,我使用了模式TopCount(Filter(…notisempty(…))。但是一种可能稍微快一点,并且似乎与命名集更兼容的模式是使用TopCount(NonEmpty(…),…)
  • A)使用命名集,B)使用[MySet].Current而不是[My Dimension].[My Hierarchy].CurrentMember在生成调用中的组合似乎也会带来适度的性能提升。
    • 注意:前面我说过命名集给我带来了麻烦。不过,有一次我切换到NonEmpty()进行空元组过滤,我对它们没有任何问题
考虑到这一点,我现在的查询是这样的

WITH
SET [Set0] as [Firms].[Firm Name].Children
SET [Set1] as generate([Set0], crossjoin([Set0].Current, TopCount(NonEmpty([Clients].[Client Name].Children, [Measures].[Amount]), 5, [Measures].[Amount])))
SET [Set2] as generate([Set1], crossjoin([Set1].Current, TopCount([Time].[Year].Children, 5, [Measures].[Amount])))
SELECT
[Measures].[Amount] on columns,
NON EMPTY [Set2] on rows
FROM Lobbying2
在本例中,我对Set1使用NonEmpty,因为Firms x Clients是稀疏的,但对Set2不使用NonEmpty,因为FirmClientPairs x Time不是稀疏的


我还注意到,使用命名集可以更容易地构造嵌套的“前五名中的前五名…”类型查询,这很有趣。

如何改进下面的MDX查询性能

让我解释一下我为提高性能所采取的步骤

SELECT non empty([Measures].[HC_ALLOCATED_CNT_ASSIGNMENT]*[BI FCT PROJ ASSIGN].[ASSIGN CATEGORY 1].[ASSIGN CATEGORY 1].MEMBERS *[BI FCT PROJ ASSIGN].[ASSIGN CATEGORY 2].[ASSIGN CATEGORY 2].MEMBERS) ON AXIS(0),([BI DIM PROJECT].[PROJECT CODE].[PROJECT CODE].MEMBERS*[BI DIM PROJECT].[UNIT CODE].[UNIT CODE].MEMBERS*
        [BI DIM PROJECT].[SUBUNIT CODE].[SUBUNIT CODE].MEMBERS*
        [BI DIM PROJECT].[CURRENT PROJECT DESCRIPTION].[CURRENT PROJECT DESCRIPTION].MEMBERS*[BI DIM PROJECT].[CURRENT BILLING TYPE].[CURRENT BILLING TYPE].MEMBERS *[BI DIM PROJECT].[CURRENT MANAGED BY].[CURRENT MANAGED BY].MEMBERS *[BI DIM PROJECT].[CURRENT PROJECT OFFSHORE OU].[CURRENT PROJECT OFFSHORE OU].MEMBERS*[BI DIM PROJECT].[CURRENT ACCOUNT NAME].[CURRENT ACCOUNT NAME].MEMBERS*[BI DIM PROJECT].[CUSTOMER CODE].[CUSTOMER CODE].MEMBERS*     [BI DIM PROJECT].[CURRENT AD MAILID].[CURRENT AD MAILID].MEMBERS *[BI DIM PROJECT].[CURRENT AM MAILID].[CURRENT AM MAILID].MEMBERS *[BI DIM PROJECT].[CURRENT PD MAILID].[CURRENT PD MAILID].MEMBERS *[BI DIM PROJECT].[CURRENT PM MAILID].[CURRENT PM MAILID].MEMBERS *[BI DIM PROJECT].[CURRENT PROJECT STATUS].[CURRENT PROJECT STATUS].MEMBERS*[BI DIM ASSOCIATE].[FULLNAME].[FULLNAME])ON AXIS(1) FROM [CUBE_IAMIS]

@到目前为止,每当我尝试在这里使用命名集时,该集都不够动态;总的来说,它总是排在前五位,而我希望每家公司都排在前五位。(到目前为止,如果我通过“with set…select”、“with dynamic set…select”、“create set”或“create dynamic set”创建集合似乎没有什么区别。尝试现有的关键字似乎也没有帮助。)因为我还没有弄清楚如何让集合按我想要的方式工作,我不确定他们是否能帮助提高性能。是否需要在前5名之前筛选->筛选([Clients].[Client Name]。子项,而不是IsEmpty([Measures].[Amount])?你试过了吗。交叉连接([Firms].[Firm Name].CurrentMember[Clients].[Clients Name].Children),为什么不进入前5名(我知道结果不一样)。。这是我所能想到的。如果没有其他供应商可以缓存集;-)@icCube我想你是建议用generate(filter(crossjoin(topcount)(filter(…)))替换generate(crossjoin(topcount(…)))。我试过这个,但它让事情变得更糟;这是我尝试过的最慢的查询变体!:)基于我的小性能测试,我开发了一个crackpot理论,将我的过滤器作为最内部的函数,可以让SSA从存储引擎(即不表示空值的引擎)检索到比其他引擎更稀疏的数据表示,这确实加快了TopCount的排序工作。不过,谢谢你们能缓存数据集的提示。好吧,你们说得对。一种解决方案是将两个维度(客户和客户)合并到一个维度中,并具有潜在的多对多关系。因此,该系统可以非常快速地消除所有“通过构造”无效的客户和客户端组合,甚至可以更好地使用子对象。性能取决于尺寸的大小。。。但我没有看到其他任何东西。[Firms].[Firm Name]。Children,表示是成员?在筛选器中添加非空([Clients].[Client Name]。Children,[Measures].[Amount]),而不是[Clients].[Client Name]。Children。。。