为何带ORDER BY PRIMARY KEY的TADIR全量查询比写入排序内表慢得多
ABAP两段SELECT语句性能差异成因
首先列出测试用的两段代码:
第一段:
SELECT * FROM tadir ORDER BY PRIMARY KEY INTO TABLE @DATA(lt_tadir).
第二段:
DATA lt_tadir TYPE SORTED TABLE OF tadir WITH UNIQUE KEY pgmid object obj_name. SELECT * FROM tadir INTO TABLE @lt_tadir.
核心成因
性能差异来自两段代码的执行路径开销差,核心是数据库层全表扫描的效率远高于主键索引全量扫描,ABAP内存排序的额外开销远低于数据库侧索引扫描的额外开销,具体拆解如下:
- 第一段代码执行开销:
- 数据库层:指定
ORDER BY PRIMARY KEY后,数据库会走主键索引扫描,按主键顺序返回数据。主键索引是B+树结构,遍历叶子节点获取数据时,要么需要频繁回表读取完整行数据(行存储表),要么需要扫描额外的索引列向量(列存储表),无法触发数据库针对全表扫描优化的大块顺序预读机制,全量读取时开销是全表扫描的数倍。 - ABAP运行时层:自动生成的
lt_tadir为标准表,数据直接追加写入,无额外排序开销。
- 数据库层:指定
- 第二段代码执行开销:
- 数据库层:未指定排序条件,直接走全表扫描读取所有数据,顺序读效率极高,开销远低于索引扫描。
- ABAP运行时层:写入排序内表时确实会触发一次内存排序,但ABAP的内存排序算法经过高度优化,对于普通业务表量级的数据,排序开销仅几毫秒到几十毫秒,完全抵消不了数据库层节省的开销。
与官方文档描述的一致性说明
你看到的官方文档描述和实际表现并不冲突:
出于性能考虑,仅当排序操作受索引支持时才应在数据库侧执行,该条件仅在指定ORDER BY PRIMARY KEY时可得到保证。
该建议的适用场景是你必须要求数据库返回排序后的结果,比如搭配UP TO n ROWS取前N条数据、或者需要分页查询的场景,这种场景下数据库侧用索引排序的收益远高于ABAP侧全量读入后排序。如果你需要全量读取数据后存入排序内表,数据库侧排序完全没有必要。
若将排序后的结果集赋值给排序内表,系统会按照排序规则再次对内部表进行重排序。
该逻辑在你的测试场景中没有触发:第一段代码自动生成的是标准表,不需要重排序;第二段代码写入的是未排序的结果集,仅会触发一次ABAP侧排序,没有重复排序的额外开销。
其他测试场景的一致性解释
你测试其他行存储、列存储表都出现第二段略快的结果,符合逻辑:不管存储引擎类型,全表扫描读取全量字段的效率都高于索引扫描+回表/多列扫描的效率,ABAP内存排序的开销相比数据库层的开销差可以忽略,因此第二段始终更快。
内容的提问来源于stack exchange,提问作者user6412004
相关产品推荐
相关产品推荐

