这是本系列的最后一个优化方案,这一篇的优化方案3是所有方案中最优秀的,它解决了优化方案2中产生的[RowNumber] 问题,使整个底层计算过程中全部步骤都没有出现数据量超过万行的情况,使性能获得了极大的提升!
研究《DAX查询计划 白皮书》中的案例(一)初始方案
研究《DAX查询计划 白皮书》中的案例(二)优化方案1
研究《DAX查询计划 白皮书》中的案例(三)优化方案(番外)
研究《DAX查询计划 白皮书》中的案例(四)优化方案2
研究《DAX查询计划 白皮书》中的案例(四)优化方案3
优化方案3
DAX 查询
// 优化方案3(修正)
EVALUATE
ADDCOLUMNS (
VALUES ( 'Calendar'[Date] ),
"Open Orders",
SUMX (
FILTER (
GENERATE (
SUMMARIZE (
Sales,
Sales[OrderDate],
Sales[ShipDate],
"Rows", COUNTROWS ( Sales )
),
DATESBETWEEN (
'Calendar'[Date],
Sales[OrderDate] + 1, // 修正此处,原版是 Sales[OpenDate]
Sales[ShipDate] - 1 )
),
'Calendar'[Date] = EARLIER ( 'Calendar'[Date] )
),
[Rows]
)
)
运行效率
以连续5次冷启动的结果进行统计,将各方案的情况列写在表格里,数字下方括号里记录的是相对前一个方案的性能变化情况。
优化方案3的表现非常亮眼,计算效率超过了之前全部的方案,总耗时已经接近个位数!
环境 | 参数 | 初始方案 | 优化方案1 | 优化方案2 | 优化方案(番外) | 优化方案3 |
---|---|---|---|---|---|---|
环境1 | 平均总耗时(毫秒) | 4389.4 | 290.4 (↑ 93.38%) |
79.6 (↑ 72.59%) |
56.8 (↑ 28.64%) |
|
SE耗时 (毫秒) |
14.4 | 4.8 |
13.6 |
4.8 | ||
SE占比 | 0.328% | 1.653% (↑ 403.83%) |
17.09% (↑ 933.67%) |
8.45% (↓50.54%) |
||
环境2 | 平均总耗时(毫秒) | 4017.0 | 300.60 (↑ 92.52%) |
76.4 (↑ 74.58%) |
53.8 (↑ 29.58%) |
12.8 (↑ 83.25%) |
SE耗时 (毫秒) |
17.2 | 5.8 (↑ 66.28%) |
18.2 |
5 |
3.4 |
|
SE占比 | 0.428% | 1.929% (↑ 350.62%) |
23.82% (↑ 1134.64%) |
9.29% (↓ 60.99%) |
26.56% (↑ 11.50%) |
白皮书中没有对此方案进行任何分析,留给读者实践,下面是我对该方案进行分析的详细记录。
存储引擎部分
依然首先查看存储引擎执行了哪些 xmSQL 查询
左侧窗口记录 SE Cache 为 1,表明有一个 xmSQL 被复用。右侧窗口记录了 4 行 Scan,其中 Line2 和 Line 4 是完全相同的,Line4 复用了 Line2 。
存储引擎一共执行 3 个 xmSQL:
1、VQ1
Line2 和 Line4,从 Calendar 表中获取 [Date] 的不重复值,包含 1 列,共 1081 行
‘Calendar’[Date]
// xmSQL VQ1
SELECT
'Calendar'[Date]
FROM 'Calendar';
2、VQ2
Line6,对 Sales 表以 Sales[OrderDate]、Sales[ShipDate] 分组并计算行数,包含 2 个数据列和 1 个值列,共 1081 行
Sales[OrderDate], Sales[ShipDate], COUNT
// xmSQL VQ2
SELECT
'Sales'[OrderDate],
'Sales'[ShipDate],
COUNT ( )
FROM 'Sales';
部分结果类似
3、VQ3
Line8,对 Sales 表以 Sales[OrderDate]、Sales[ShipDate] 分组,即获取 Sales 表中{Sales[OrderDate], Sales[ShipDate]} 的不重复值对,共 1081 行
Sales[OrderDate], Sales[ShipDate]
// xmSQL VQ3
SELECT
'Sales'[OrderDate],
'Sales'[ShipDate]
FROM 'Sales';
部分结果为:
存储引擎部分 3 个 xmSQL 查询都没有出现 [RowNumber]。
公式引擎部分
逻辑查询计划
AddColumns: RelLogOp DependOnCols()() 0-1 RequiredCols(0, 1)('Calendar'[Date], ''[Open Orders])
├── Scan_Vertipaq: RelLogOp DependOnCols()() 0-0 RequiredCols(0)('Calendar'[Date])
└── SumX: ScaLogOp DependOnCols(0)('Calendar'[Date]) Integer DominantValue=BLANK
├── Filter: RelLogOp DependOnCols(0)('Calendar'[Date]) 1-4 RequiredCols(0, 1, 2, 3, 4)('Calendar'[Date], 'Sales'[OrderDate], 'Sales'[ShipDate], ''[Rows], 'Calendar'[Date])
│ ├── CrossApply: RelLogOp DependOnCols()() 1-4 RequiredCols(1, 2, 3, 4)('Sales'[OrderDate], 'Sales'[ShipDate], ''[Rows], 'Calendar'[Date])
│ │ ├── AddColumns: RelLogOp DependOnCols()() 1-3 RequiredCols(1, 2, 3)('Sales'[OrderDate], 'Sales'[ShipDate], ''[Rows])
│ │ │ ├── GroupBy_Vertipaq: RelLogOp DependOnCols()() 1-15 RequiredCols(1, 2)('Sales'[OrderDate], 'Sales'