使用次键提高内部表性能

学习目标

  • 使用次键提高内部表性能

次键

该视频概述了使用和不使用键值读取内部表之间的差异。

视频:本节含 SAP 官方视频(视频 ID 1_almgkyzo),需在 learning.sap.com 在线观看。

要使用不属于主键的字段加速访问内部表,可以向内部表的定义添加一个或多个次键。

如图所示,内部表的次关键字可以是排序或散列。与内部表的主键一样,排序键可以是唯一的,也可以是非唯一的,而散列键必须始终是唯一的。

观看此视频,了解如何使用次键通过次键提高内部表性能。

视频:本节含 SAP 官方视频(视频 ID 1_lfw7mgv2),需在 learning.sap.com 在线观看。

如果内部表具有非唯一次键,则直到程序使用该键对表进行寻址后,系统才会创建该键。首次创建键值会花费额外的运行时间,因此首次读取访问通常比未使用键值更昂贵。但是,一旦键值存在,后续读取访问速度就会非常快(并且比不使用次键读取表要快得多)。

如果更改表内容,系统不会自动更新索引,而是等待查看是否有任何使用次关键字的读取访问。首次后续读取访问时,系统会更新次关键字。这不像创建密钥那样昂贵,但更新成本适中。

唯一辅助键有两个用途 - 首先加速访问表,其次确保表中所有行的键组合唯一。因此,系统必须始终保持键值最新,并对非唯一的次键使用不同的更新策略。

更改内部表的内容(填充或更改其内容)的任何操作都会导致创建(首次访问)或更新索引(后续访问)。读取访问始终很快,因为次级索引始终是最新的。

试用:次键

  1. 创建实施接口 IF_OO_ADT_CLASSRUN 的新类。

  2. 将以下代码片段复制到方法 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' ).
  1. 切换到 局部类型 标签并将以下代码片段复制到编辑器中:

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.
  1. 选择 Ctrl + F3 激活类。

  2. 右键单击编辑器,然后选择 参数文件作为... → ABAP 应用程序(控制台) 。

  3. 在详细信息 中,取消选中复选框 SQL 数据库访问 并选择 完成 。

  4. 切换到 ABAP 分析器 透视图并双击跟踪项目(可能需要先刷新显示)。

  5. 选择 Hit List 。

  6. 比较方法 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

步骤

  1. 将类 /LRN/CL_S4D401_ITS_TABLE_KIND 复制到您自己的包中的类(建议名称:ZCL_##_SOLUTION,其中 ## 代表组编号)。

  2. 在项目浏览器中,右键单击类 /LRN/CL_S4D401_ITS_TABLE_KIND 以打开上下文菜单。

  3. 从上下文菜单中,选择复制....

  4. 在包字段中输入的名称。在名称字段中,输入 ZCL_##_SOLUTION,其中 ## 代表组编号。

  5. 选择下一步

  6. 确认传输请求并选择完成

  7. 激活复制。

  8. Ctrl + F3 激活类。

任务 2: 定义次键

在局部类 LCL_PASSENGER_FLIGHTS 中,将 flights_buffer 属性转换为散列表。然后定义仅在指定 carrier_id 字段时优化访问的次键。

步骤

  1. 导航到本地类 LCL_PASSENGER_FLIGHT 中静态属性 flights_buffer 的定义。

  2. 例如,展开概要视图中的节点 LCL_PASSENGER_FLIGHT,然后选择 FLIGHTS_BUFFER

  3. 调整 flights_buffer 属性的定义。将表类型设置为 HASHED TABLE 并相应地调整主键定义。

  4. 如下调整代码:

注意

请注意,散列表的键值必须唯一。

*  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.
  1. 使用关键字段 carrier_id 定义次键(建议名称:**sk_**carrier)。

  2. 如下调整代码:

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.
  1. 分析问题视图中的条目。

  2. 分析编辑器下方的 问题 视图。

  3. 双击结果以访问相应代码。

任务 3: 使用次键

在仅指定 carrier_id 字段的本地类 LCL_PASSENGER_FLIGHT 中调整对静态属性 flights_buffer 的访问。确保在这些访问中使用新的次密钥。

步骤

  1. 导航到函数 line_exists 的调用。使用 语句使用次键。

  2. 如下调整代码:

IF NOT line_exists( flights_buffer[
KEY sk_carrier
COMPONENTS carrier_id = i_carrier_id ]
).

注意

COMPONENTS 附加项是可选的,可以省略。我们在这里用它来澄清。

  1. 导航到表理解并确保使用次键。

  2. 如下调整代码:

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 )
)
).
  1. 以控制台应用形式激活并测试全局类。

  2. Ctrl + F3

  3. F9