我需要从数据库中编程客户搜索。
我知道数据库是用来管理大量数据的。但是我的"导师"告诉我尽可能少地与数据库互动。
是否最好将整个数据库表读入内部表,然后根据用户输入的参数进行过滤:
SELECT * FROM customer INTO TABLE it_customer.
LOOP AT it_customer INTO wa.
WHERE .... IN ...
APPEND wa TO output.
ENDLOOP.
或者只是直接访问数据库表?
SELECT * FROM customer
INTO wa
WHERE ... in ...
APPEND wa TO output.
ENDSELECT.
确实,数据库访问被认为是一种昂贵的操作。 习惯于以正确的方式访问数据库绝对会提高您的系统性能。
通常,减少数据库访问次数是一个很好的起点。然而,这并不是唯一要以">正确方式"考虑的因素。
让我们特别看看您的案例:
* A single DB access:
SELECT *
FROM customer
INTO CORRESPONDING FIELDS OF TABLE @lt_customer.
* Then some manipualtion.
* ...
陷阱:
- 如前所述,从数据库到应用程序服务器的数据流是昂贵的。不仅访问量是一个因素,而且传输的数据量也是一个因素。如果不是需要所有客户(例如,对于客户个人信息屏幕),则将所有其他不需要的客户转移到应用程序服务器将会产生很大的开销。
- 如果只执行一次,例如在流程开始时,选择整个表可能是可以的。但是,在许多流程中,数据库在流程中途会更改(例如,如果它是所有客户的概览屏幕)。在这种情况下,您将不得不刷新数据,并且使用另一个
select *
执行此操作可能是错误的。 - 数据库访问确实很昂贵,但内部操作也不是免费的。执行
select *
将给出lt_customer
中N
行的起始器,当N
是客户数据库表中的记录数时。有时不可避免地要按n^2
顺序甚至更多顺序进行计算。随着N
的增长,处理它所需的时间也在增加。
我现在没时间了。当我有更多的时间时,我会尝试扩展更多。祝你好运。
附言SELECT... ENDSELECT.
被认为是一种不好的做法。您可以在此处阅读示例。
SAP 在其性能说明中陈述的主要原则是:
保持低点击次数
这意味着 WHERE 条件永远不应该像您打算的那样为空。切勿读取整个数据库。
保持低读取次数原则仅在第三位,即在大量数据上不太重要。但是你也不应该滥用它,也不应该像你的第二个变体那样在循环中使用数据库操作,除非你正在做一些特殊的事情,有一些特殊要求。
多说一点,您的代码违反了保持低数据量原则,因为您正在获取所有列而不是所需的列。避免在 SELECT 中使用 *,除非您确实使用了所有列。
所以答案是:使用第一段代码(但在 SELECT 中使用 WHERE!),它会更有效率。在大多数情况下,ABAP 操作比数据库操作便宜。
关于此主题的有用博客:
https://blogs.sap.com/2014/05/21/a-complete-guide-to-opensql-statements-step-by-step-tutorial-with-screenshots/
SELECT the, fields, you, really, need
FROM customer
INTO TABLE @DATA(customers)
WHERE some_attribute = @some_value
OR some_id IN @some_range.
如果记录数量很大,您可能需要在包中处理数据:
SELECT the, fields, you, really, need
FROM customer
INTO TABLE @DATA(customers)
WHERE some_attribute = @some_value
OR some_id IN @some_range
PACKAGE SIZE 1024.
" some processing
ENDSELECT
- 一步读取尽可能多的记录,以将昂贵的数据库往返次数降至最低。
- 仅选择真正需要的列,并使用 WHERE 来最小化内存占用和需要传输的数据量。
使用 SELECT ...进入表格
当你得到一个更好的导师1时,将你的代码重构为合理的代码会容易得多。
仅当it_customer
导致内存转储时,才应使用 SELECT...结束选择。
1)或DBA或CTO,无论谁对当前的非常糟糕的政策负责