使用次键提高内部表性能
学习目标
使用次键提高内部表性能
次键
该视频概述了使用和不使用键值读取内部表之间的差异。
视频:本节含 SAP 官方视频(视频 ID
1_almgkyzo),需在 learning.sap.com 在线观看。
要使用不属于主键的字段加速访问内部表,可以向内部表的定义添加一个或多个次键。

如图所示,内部表的次关键字可以是排序或散列。与内部表的主键一样,排序键可以是唯一的,也可以是非唯一的,而散列键必须始终是唯一的。
观看此视频,了解如何使用次键通过次键提高内部表性能。
视频:本节含 SAP 官方视频(视频 ID
1_lfw7mgv2),需在 learning.sap.com 在线观看。

如果内部表具有非唯一次键,则直到程序使用该键对表进行寻址后,系统才会创建该键。首次创建键值会花费额外的运行时间,因此首次读取访问通常比未使用键值更昂贵。但是,一旦键值存在,后续读取访问速度就会非常快(并且比不使用次键读取表要快得多)。
如果更改表内容,系统不会自动更新索引,而是等待查看是否有任何使用次关键字的读取访问。首次后续读取访问时,系统会更新次关键字。这不像创建密钥那样昂贵,但更新成本适中。

唯一辅助键有两个用途 - 首先加速访问表,其次确保表中所有行的键组合唯一。因此,系统必须始终保持键值最新,并对非唯一的次键使用不同的更新策略。
更改内部表的内容(填充或更改其内容)的任何操作都会导致创建(首次访问)或更新索引(后续访问)。读取访问始终很快,因为次级索引始终是最新的。
试用:次键
创建实施接口 IF_OO_ADT_CLASSRUN 的新类。
将以下代码片段复制到方法 if_oo_adt_classrun~main() 的实施部分
data(object) = new lcl_flights( ).
* object->read_primary( ).
object->read_non_key( ).
object->read_secondary_1( ).
object->read_secondary_2( ).
object->read_secondary_3( ).
out->write( 'Done' ).
切换到 局部类型 标签并将以下代码片段复制到编辑器中:
CLASS lcl_flights DEFINITION.
PUBLIC SECTION.
METHODS constructor.
METHODS read_primary.
METHODS read_non_key.
METHODS read_secondary_1.
METHODS read_secondary_2.
METHODS read_secondary_3.
PRIVATE SECTION.
DATA connections TYPE SORTED TABLE OF Zs4d401_flights WITH NON-UNIQUE KEY carrier_id connection_Id flight_date.
DATA connections_sk TYPE SORTED TABLE OF Zs4d401_flights WITH NON-UNIQUE KEY carrier_id connection_id flight_date
WITH NON-UNIQUE SORTED KEY k_plane COMPONENTS plane_type_id.
ENDCLASS.
CLASS lcl_flights IMPLEMENTATION.
METHOD constructor.
SELECT FROM Zs4d401_flights FIELDS * INTO TABLE @connections.
SELECT FROM Zs4d401_flights FIELDS * INTO TABLE @connections_sk.
ENDMETHOD.
METHOD read_non_key.
LOOP AT connections INTO DATA(connection) WHERE plane_type_id = '737-800'.
ENDLOOP.
ENDMETHOD.
METHOD read_primary.
DATA count TYPE i VALUE 1.
LOOP AT connections INTO DATA(connection) WHERE carrier_id = 'LH' AND connection_id = '0405' .
count += 1.
ENDLOOP.
ENDMETHOD.
METHOD read_secondary_1.
LOOP AT connections_sk INTO DATA(connection) USING KEY k_plane WHERE plane_type_id = '737-800'.
ENDLOOP.
ENDMETHOD.
METHOD read_secondary_2.
LOOP AT connections_sk INTO DATA(connection) USING KEY k_plane WHERE plane_type_id = '737-800'.
ENDLOOP.
ENDMETHOD.
METHOD read_secondary_3.
LOOP AT connections_sk INTO DATA(connection) USING KEY k_plane WHERE plane_type_id = '737-800'.
ENDLOOP.
ENDMETHOD.
ENDCLASS.
选择 Ctrl + F3 激活类。
右键单击编辑器,然后选择 参数文件作为... → ABAP 应用程序(控制台) 。
在详细信息 中,取消选中复选框 SQL 数据库访问 并选择 完成 。
切换到 ABAP 分析器 透视图并双击跟踪项目(可能需要先刷新显示)。
选择 Hit List 。
比较方法 read_primary( ) 、 read_secondary_2( ) 、 read_secondary_1( ) 和 read_secondary_3( ) 的运行时。
定义和使用次键
您想要进一步改进对静态属性 flights_buffer 的访问。您将将其定义为具有附加排序次关键字的散列表,而不是仅包含一个键的排序表,以便在仅指定 carrier_id 字段时优化访问。
模板:
/LRN/CL_S4D401_ITS_TABLE_KIND(全局类)
解决方案:
/LRN/CL_S4D401_ITS_SEC_KEY(全局类)
任务 1: 复制模板(可选)
复制模板类 /LRN/CL_S4D401_ITS_TABLE_KIND。如果已完成上一练习,则可以跳过此任务并继续编辑类 ZCL_##_SOLUTION。
步骤
将类
/LRN/CL_S4D401_ITS_TABLE_KIND复制到您自己的包中的类(建议名称:ZCL_##_SOLUTION,其中 ## 代表组编号)。在项目浏览器中,右键单击类
/LRN/CL_S4D401_ITS_TABLE_KIND以打开上下文菜单。从上下文菜单中,选择复制....
在包字段中输入包的名称。在名称字段中,输入
ZCL_##_SOLUTION,其中 ## 代表组编号。选择下一步。
确认传输请求并选择完成。
激活复制。
按
Ctrl + F3激活类。
任务 2: 定义次键
在局部类 LCL_PASSENGER_FLIGHTS 中,将 flights_buffer 属性转换为散列表。然后定义仅在指定 carrier_id 字段时优化访问的次键。
步骤
导航到本地类
LCL_PASSENGER_FLIGHT中静态属性flights_buffer的定义。例如,展开概要视图中的节点
LCL_PASSENGER_FLIGHT,然后选择 FLIGHTS_BUFFER。调整
flights_buffer属性的定义。将表类型设置为HASHED TABLE并相应地调整主键定义。如下调整代码:
注意
请注意,散列表的键值必须唯一。
* CLASS-DATA: flights_buffer
* TYPE SORTED TABLE OF st_flights_buffer
* WITH NON-UNIQUE KEY carrier_id connection_id flight_date.
CLASS-DATA: flights_buffer
TYPE HASHED TABLE OF st_flights_buffer
WITH UNIQUE KEY carrier_id connection_id flight_date.
使用关键字段
carrier_id定义次键(建议名称:**sk_**carrier)。如下调整代码:
CLASS-DATA: flights_buffer
TYPE HASHED TABLE OF st_flights_buffer
WITH UNIQUE KEY carrier_id connection_id flight_date
WITH NON-UNIQUE SORTED KEY sk_carrier COMPONENTS carrier_id.
分析问题视图中的条目。
分析编辑器下方的 问题 视图。
双击结果以访问相应代码。
任务 3: 使用次键
在仅指定 carrier_id 字段的本地类 LCL_PASSENGER_FLIGHT 中调整对静态属性 flights_buffer 的访问。确保在这些访问中使用新的次密钥。
步骤
导航到函数
line_exists的调用。使用 语句使用次键。如下调整代码:
IF NOT line_exists( flights_buffer[
KEY sk_carrier
COMPONENTS carrier_id = i_carrier_id ]
).
注意
COMPONENTS 附加项是可选的,可以省略。我们在这里用它来澄清。
导航到表理解并确保使用次键。
如下调整代码:
r_result = VALUE #(
FOR <flight> IN flights_buffer
USING KEY sk_carrier
WHERE ( carrier_id = i_carrier_id ) (
NEW lcl_passenger_flight(
i_carrier_id = <flight>-carrier_id
i_connection_id = <flight>-connection_id
i_flight_date = <flight>-flight_date )
)
).
以控制台应用形式激活并测试全局类。
按
Ctrl + F3。按
F9。