乐趣区

关于abap:MapReduce-思想在-ABAP-编程中的一个实际应用案例

ABAP 是一门企业级利用编程语言,其 740 版本于 2013 年公布,削减了许多新的语法和关键字:

其中一个亮点就是新引入的 REDUCE 关键字。这个关键字的作用和在大规模数据集并行计算畛域里宽泛应用的 Map-Reduce 编程模型中的 Reduce 操作相似,能够依照字面意思了解为 归约

什么是 Map-Reduce 思维?

Map-Reduce 是一种编程模型和相干实现,用于在集群上应用并行分布式算法,生成和解决大规模数据集。

一个 Map-Reduce 程序由一个 Map 过程和一个 Reduce 办法组成。Map 过程负责执行过滤和排序,例如将学生按名字排序到队列中,每个名称由一个队列保护。

Reduce 办法负责执行汇总操作,例如计算学生的数量。
Map-Reduce 零碎通过编排分布式服务器,来并行运行各种工作,管理系统各个局部之间的所有通信和数据传输,以及提供数据冗余,实现容错机制。

下图是 Map Reduce 框架的工作步骤,统计一个海量输出数据集 (比方大于 1TB) 中的单词呈现次数。工作步骤蕴含 Splitting, Mapping, Shuffling, Reducing 以失去最初的输入后果。

Map-Reduce 编程模型曾经宽泛使用于大数据处理畛域的工具和框架,比方 Hadoop 之中。

Map-Reduce 在 CRM 零碎中的一个理论利用

咱们来看一个笔者工作中的理论工作。我须要在某个 CRM 测试零碎上做个统计,列出在数据库表 CRM_JSTO 里,OBTYP(Object Type) 和 STSMA(Status Schema) 这两列领有雷同值的内表行的个数。大家能够把 OBTYP 和 STSMA 两列具备雷同值的内表行 这个形容,类比成上图中反复呈现的单词。

下图是零碎中数据库表 CRM_JSTO 的局部行:

下图是笔者最终实现的统计后果:

测试零碎上数据库表总的行数超过 55 万行,其中有 90279 行,只保护了 OBTYP 为 TGP,而没有保护 STSMA.

排名第二的是 COH 和 CRMLEAD 的组合,呈现了 78722 次。

上图这个后果是怎么统计进去的呢?

稍稍做过一些 ABAP 开发的敌人们,肯定会立刻写出上面的代码:

利用 SELECT COUNT 间接在数据库层实现统计工作。这也是 SAP 举荐的做法,即所谓 Code pusudown 准则,即能放到 HANA 数据库层面进行的操作,就尽量放进去,以充分利用 HANA 弱小的计算能力。在数据库可能实现计算逻辑的前提下,尽量避免把计算逻辑放到 Netweaver ABAP 应用层去做。

不过,咱们也须要留神到这种形式的局限性。SAP CTO 已经有过一句名言:

There is no future with ABAP alone
There is no future in SAP without ABAP

将来的 ABAP 会走向凋谢,互联的路线。回到这个需要自身,假如待检索的输出数据不是从 ABAP 数据库表中来,而是来自 HTTP 申请,或者第三方零碎发过来的 IDOC,此时咱们无奈再应用 OPEN SQL 自身的 SELECT COUNT 操作,而只能在 ABAP 应用层解决这个问题。

上面介绍两种用 ABAP 编程语言实现这一需要的解决方案。

第一种形式比拟传统,实现在办法 get_result_traditional_way 里:

ABAP 的 LOOP AT GROUP BY 这个关键字组合几乎就像是为这个需要量身定做个别:给 GROUP BY 指定 obtyp 和 stsma 这两列,而后 LOOP AT 会主动将输出内表的行记录依据这两列的值进行分组,每组行记录的个数通过关键字 GROUP SIZE 主动计算出来,每组各自的 obtyp 和 stsma 的值,以及组外行记录的条目数,存储在 REFERENCE INTO 指定的变量 group_ref 里。ABAP 开发人员须要做的事件,只是简略地把这些后果存储到输入内表即可。

第二种方法,就是本文题目所述,应用 ABAP 740 新引入的 REDUCE 关键字:

REPORT zreduce1.

DATA: lt_status TYPE TABLE OF crm_jsto.

SELECT * INTO TABLE lt_status FROM crm_jsto.

DATA(lo_tool) = NEW zcl_status_calc_tool( ).

lo_tool = REDUCE #( INIT  o = lo_tool
                          local_item = VALUE zcl_status_calc_tool=>ty_status_result( )
                     FOR GROUPS <group_key> OF <wa> IN lt_status
                      GROUP BY (obtyp = <wa>-obtyp stsma = <wa>-stsma)
       ASCENDING NEXT local_item = VALUE #( obtyp = <group_key>-obtyp
                                             stsma = <group_key>-stsma
       count = REDUCE i( INIT sum = 0 FOR m IN GROUP <group_key>
               NEXT sum = sum + 1 ) )
       o = o->add_result(local_item) ).

DATA(ls_result) = lo_tool->get_result().

下面的代码乍一看可能感觉有点艰涩,但仔细阅读后发现这种形式实质上也采纳了和办法一 LOOP AT GROUP BY 同样的分组策略——依据 obtyp 和 stsma 分组,这些子组通过变量 group_key标识,而后通过第 10 行的 REDUCE 关键字,通过累加的形式,手动计算这个组的条目数——把一个大的输出集依据 GROUP BY 指定的条件归约成一个个规模更小的子集,而后别离针对子集进行计算——这就是 REDUCE 关键字通过字面含意传递给 ABAP 开发人员的解决思维。

总结和比拟一下这三种实现形式:当待统计的数据源为 ABAP 数据库表时,肯定优先选用 OPEN SQL 的形式,使计算逻辑在数据库层实现,以获得最佳的性能。

当数据源并非 ABAP 数据库表,而分组统计的需要为简略的计数操作 (COUNT) 时, 优先用 LOOP AT … GROUP BY … GROUP SIZE,使得计数操作通过 GROUP SIZE 在 ABAP kernel 实现,以取得较好的性能。

当数据源并非 ABAP 数据库表,而分组统计的需要为自定义的逻辑时,用本文介绍的第三种 REDUCE 解法,将自定义统计逻辑写在第 11 行的 NEXT 关键字后。

三种解法的性能评测

我编写了一个简略的报表进行性能评测:

DATA: lt_status TYPE zcl_status_calc_tool=>tt_raw_input.

SELECT * INTO TABLE lt_status FROM crm_jsto.

DATA(lo_tool) = NEW zcl_status_calc_tool( ).

zcl_abap_benchmark_tool=>start_timer( ).
DATA(lt_result1) = lo_tool->get_result_traditional_way(lt_status).
zcl_abap_benchmark_tool=>stop_timer( ).

zcl_abap_benchmark_tool=>start_timer( ).
lo_tool = REDUCE #( INIT  o = lo_tool
                          local_item = VALUE zcl_status_calc_tool=>ty_status_result( )
                     FOR GROUPS <group_key> OF <wa> IN lt_status
                      GROUP BY (obtyp = <wa>-obtyp stsma = <wa>-stsma)
       ASCENDING NEXT local_item = VALUE #( obtyp = <group_key>-obtyp
                                             stsma = <group_key>-stsma
       count = REDUCE i( INIT sum = 0 FOR m IN GROUP <group_key>
               NEXT sum = sum + 1 ) )
       o = o->add_result(local_item) ).

DATA(lt_result2) = lo_tool->get_result( ).
zcl_abap_benchmark_tool=>stop_timer( ).

ASSERT lt_result1 = lt_result2.

测试数据如下:

这三种解法的性能顺次递加,不过实用的场合和灵便水平顺次递增。

LOOP AT ... GROUP BY ... GROUP SIZE 这种解决方案,在笔者工作的 ABAP 测试服务器上,解决 55 万条记录,用了 0.3 秒,而 REDUCE 则需破费 0.8 秒, 两种解法的性能处于同一数量级之内。

总结

Map-Reduce 是一种编程模型和相干实现,用于在集群上应用并行分布式算法,生成和解决大规模数据集。ABAP 编程语言从语言层面反对对大规模数据的 REDUCE 操作。本文分享了笔者工作中应用 Map-Reduce 思路解决大规模数据集的一个理论案例,并与传统的另外两种解决方案做了比拟。在性能不逊于传统解决方案的前提下,基于 Map-Reduce 的解决方案,具备更为宽泛的利用场合和可扩展性。心愿本文分享的内容对大家应用 ABAP 解决相似问题时有所启发,感激浏览。

退出移动版