SAP HANA 1.0 SPS12中WITH子句与多聚合查询的性能对比问询
先给大家理清楚背景:咱们用的是SAP HANA 1.0 SPS12,手里有一张500万行的日维度表table_1,表结构如下:
select trans_date, article, measure1, measure2 from table_1
需求很明确:要按day-1、day-2、WTD、WTD-1,还有后续的MTD、MTD-1、YTD等多个时间维度,聚合measure1和measure2的数据。现在有两种实现思路,咱们来掰扯掰扯哪种性能更好,尤其是结合HANA这个内存数据库的特性。
两种方案对比
方案1:多独立查询+UNION ALL
这是你最初给出的示例写法,每个时间维度单独写查询,再用UNION ALL拼接结果:
select 'day-1', sum(measure1), sum(measure2) from table1 where trans_date = add_days(current_date, -1) group by 'day-1' union all select 'day-2', sum(measure1), sum(measure2) from table1 where trans_date >= add_days(current_date, -2) group by 'day-2' union all select 'WTD', sum(measure1), sum(measure2) from table1 where trans_date >= add_days(current_date, -7) group by 'WTD' union all select 'WTD-1', sum(measure1), sum(measure2) from table1 where trans_date >= add_days(current_date, -15) and trans_Date <= add_days(current_date, -7) group by 'WTD-1'
方案2:WITH子句预取数据再拆分聚合
先通过WITH子句把需要的一年数据捞出来,再基于这个中间结果做各个时间维度的聚合:
WITH t1 as ( select trans_date, measure1, measure2 from table1 where trans_date >= add_days(current_date, -365) ) select 'day-1', sum(measure1), sum(measure2) from t1 where trans_date = add_days(current_date, -1) group by 'day-1' union all select 'day-2', sum(measure1), sum(measure2) from t1 where trans_date >= add_days(current_date, -2) group by 'day-2' union all select 'WTD', sum(measure1), sum(measure2) from t1 where trans_date >= add_days(current_date, -7) group by 'WTD' union all select 'WTD-1', sum(measure1), sum(measure2) from t1 where trans_date >= add_days(current_date, -15) and trans_Date <= add_days(current_date, -7) group by 'WTD-1'
(注:原示例里WITH子句中的sum()是笔误,这里做了修正——咱们需要原始数据来按不同时间范围聚合,提前sum会丢失明细,导致结果错误)
性能分析:为什么WITH子句更适合HANA?
你提到Oracle里WITH子句会物化到内存复用,那HANA作为内存数据库,是不是这个特性就没用了?其实不然,咱们得结合HANA的执行逻辑来看:
基表扫描次数是关键
- 方案1里,每个
UNION ALL分支都会单独扫描一次table_1,再过滤对应的日期范围。如果后续要加MTD、YTD等更多维度,扫描次数会跟着涨,500万行的表反复扫描,累积的开销肯定不小。 - 方案2里,WITH子句的
t1只扫描一次table_1,把最近一年的数据捞出来(不管这部分是几万还是几十万行,总归是一次扫描),后续所有维度的聚合都基于t1来做,直接避免了重复扫描基表的开销。
- 方案1里,每个
HANA对WITH子句的处理逻辑
HANA的查询优化器不会盲目物化,但只要t1的结果集不是特别大(比如一年数据远小于500万总行数),它大概率会把t1物化到内存里,后续的聚合查询直接复用这个数据集,节省了大量重复读取和过滤的时间。
就算不物化,HANA的列式存储特性也能让扫描t1的开销远低于重复扫描基表——因为列式存储只读取咱们需要的trans_date、measure1、measure2三列,而方案1每次扫描也读这些列,但多次扫描的总开销还是更高。优势的显著性
当你的时间维度分支越多(比如从4个扩展到10个以上),方案2的性能优势会越明显。重复扫描基表的开销是线性增长的,而WITH子句只需要一次扫描,这个差距会越来越大。
结论
在SAP HANA 1.0 SPS12中,用WITH子句预取所需数据再拆分聚合的方案,性能要优于多独立查询+UNION ALL的写法,尤其是当你需要支持更多时间维度时,能显著减少不必要的基表扫描,充分利用内存数据库的特性提升效率。
内容的提问来源于stack exchange,提问作者Anirudh D

