5

是否有与大查询性能相关的一般ABAP 特定提示?SELECT

特别是,是否可以一劳永逸地关闭FOR ALL ENTRIES INvs的问题JOIN

4

8 回答 8

13

一些(或多或少)特定于 ABAP 的提示:

避免 SELECT * 在不需要的地方,尽量只选择需要的字段。原因:每个值在此过程中可能会被多次映射(DB Disk --> DB Memory --> Network --> DB Driver --> ABAP internal)。如果您仍然不需要这些字段,则很容易节省 CPU 周期。如果您选择 * 一个包含 STRING 等 BLOB 字段的表,请务必小心,这会完全破坏您的数据库性能,因为 blob 内容通常存储在不同的页面上。

不要 SELECT ... ENDSELECT 用于中小型结果集,请改用 SELECT ... INTO TABLE。原因: SELECT ... INTO TABLE 执行一次提取并且不会保持游标打开,而 SELECT ... ENDSELECT 通常会为每个循环迭代提取一行。

这是一种都市神话——SELECT用作循环语句不会降低性能。但是,这将在循环期间保持打开的光标,这可能会导致不需要的(但不是严格与性能相关的)效果。

对于大型结果集,请使用游标和内部表。 原因:同上,避免占用过多的堆空间。

不要 ORDER BY,而是使用 SORT。 原因:应用服务器的可扩展性更好。

小心嵌套的 SELECT 语句。 虽然它们对于小型“内部结果集”非常方便,但如果嵌套查询返回大型结果集,它们会占用大量性能。

衡量,衡量,衡量 如果您担心性能,请不要假设任何事情。创建一组具有代表性的测试数据并针对不同的实现运行测试。了解如何使用 ST05 和 SAT。

没有办法“一劳永逸”地结束你的第二个问题。首先, FOR ALL ENTRIES IN 'join' 一个数据库表和一个内部(内存)表,而 JOIN 只对数据库表进行操作。由于数据库对内部 ABAP 内存一无所知,因此 FOR ALL ENTRIES IN 语句将转换为一组 WHERE 语句 - 只需尝试使用 ST05 来跟踪它。其次,在使用 FOR ALL ENTRIES IN 时,不能从第二个表中添加值。第三,请注意 FOR ALL ENTRIES IN 总是意味着 DISTINCT。还有一些其他的陷阱 - 请务必查阅在线 ABAP 参考资料,它们都列在那里。

如果第二个表中的记录数很少,则两个语句在性能上应该或多或少相等 - 数据库优化器应该只预先选择第二个表中的所有值并使用智能连接算法过滤第一个表。我的建议:使用任何感觉良好的东西,不要试图将您的代码调整为难以辨认。

如果第二个表中的记录数超过某个值,Bad Things [TM] 发生 FOR ALL ENTRIES IN - 表的内容被分成多个集合,然后查询被转换(见上文)并重新运行对于每组。

于 2009-12-28T18:48:52.183 回答
5

另一个注意事项:“Avoid SELECT *”语句通常是正确的,但我可以告诉你它在哪里是错误的。
当您无论如何都要占用大部分字段时,并且您有多个查询(在同一个程序中,或可能在同一时间运行的不同程序中)占用大部分字段,尤其是当它们不同时缺少的字段。

这是因为应用服务器数据缓冲区基于选择查询签名。如果您确保使用相同的查询,那么您可以确保可以使用缓冲区而不是再次访问数据库。在这种情况下,SELECT * 比选择 90% 的字段要好,因为您使缓冲区更有可能被使用。

另请注意,在我测试的最后一个版本中,ABAP DB 层还不够聪明,无法将 SELECT A, B 识别为与 SELECT B, A 相同,这意味着您应该始终将获取的字段按相同的顺序排列(最好是表顺序)以再次确保应用程序上的数据缓冲区得到充分利用。

于 2010-02-08T13:59:30.517 回答
3

我通常遵循 SAP 的 pdf 中所述的规则:“使用 ABAP 进行高效数据库编程” 它显示了许多优化查询的技巧。

于 2009-12-28T12:00:22.753 回答
2

这个问题永远不会被完全回答。

用于访问数据库的 ABAP 语句被整个系统的不同组件(SAP 和 DB)多次解释。每个组件的行为取决于组件本身、其版本和设置。解释的主要部分在 SAP 端的 DB 适配器中完成。

达到最大性能的唯一可行方法是测量特定系统(SAP 版本和数据库供应商和版本)。

于 2010-01-04T08:38:39.547 回答
1

交易 SE30 中也有相当丰富的提示和技巧。它甚至允许您(取决于授权)编写自己的代码片段并对其进行测量。

不幸的是,我们无法结束“针对所有条目”与加入辩论,因为它非常依赖于您的环境设置方式、您使用的数据库服务器、表索引的效率等。

简单的答案是让数据库服务器尽可能多地做。对于“所有条目”与加入问题,这意味着加入。除了每个有经验的 ABAP 程序员都知道事情从来没有这么简单。您必须尝试不同的场景并像 vwegert 所说的那样进行测量。还要记住在您的实时系统中进行测量,因为有时硬件配置或数据集明显不同,因此您的实时系统中的结果与测试完全不同。

于 2010-01-03T12:43:02.157 回答
1

我通常遵循以下约定:

  1. 从不做select *,只选择必填字段。
  2. 切勿使用“进入对应表”来创建具有所有必需字段的本地结构。
  3. 在 where 子句中,尽量使用尽可能多的主键。
  4. 如果选择获取单个记录并且所有主键都包含在 where 子句中,则使用Select single,否则使用SELECT UP TO TO 1 ROWS, ENDSELECT
  5. 尝试使用 Join 语句来连接表,而不是使用FOR ALL ENTRIES.
  6. 如果无法避免所有条目,请确保内部表不为空并删除重复条目以提高性能。
于 2016-10-08T15:21:03.423 回答
0

除了其他答案之外,还有两点:

  • 通常您JOIN用于数据库中的两个或多个表,并用于FOR ALL ENTRIES IN将数据库表与内存中的表连接起来。如果可以的话,JOIN.

  • 通常IN操作员比FOR ALL ENTRIES IN. 但是内核会转换IN成一个很长的选择语句。这种语句的长度是有限的,当它变得太长时你会得到一个转储。FOR ALL ENTRIES IN在这种情况下,尽管存在性能影响,您仍被迫使用。

于 2017-08-22T22:23:23.143 回答
0

使用内存数据库技术,最好使用 JOIN 和 SUM 等数据库聚合函数在数据库端完成所有数据和计算。

但如果你不能,至少尽量避免在循环中访问数据库。当然,还要避免在不使用索引的情况下读取数据库。

于 2019-04-09T10:06:27.943 回答