ABAP Cloud Performance Optimization: 10 Quick Wins (2025)

Category
Performance
Published
Author
Johannes

Performance problems in ABAP Cloud? These 10 Quick Wins bring immediate improvements - with code examples.

Performance Mindset

Golden Rules:

  1. Measure First - Don’t guess, measure!
  2. DB > ABAP - Push work to database
  3. Batch > Loop - Bundle operations
  4. Cache Smart - But don’t over-optimize

1. Avoid SELECT Without WHERE

Bad (loads EVERYTHING)

SELECT * FROM I_Customer
INTO TABLE @DATA(lt_customers).
LOOP AT lt_customers INTO DATA(ls_customer)
WHERE Country = 'DE'.
" Processing
ENDLOOP.

Problem: 1M rows loaded, 950k discarded!

Good (WHERE in DB)

SELECT Customer, CustomerName, Country
FROM I_Customer
WHERE Country = 'DE'
INTO TABLE @DATA(lt_customers).

Speedup: ~95% (with 1M rows)


2. Avoid SELECT in Loops

Bad (N+1 Problem)

LOOP AT lt_orders INTO DATA(ls_order).
" SELECT per iteration!
SELECT SINGLE CustomerName
FROM I_Customer
WHERE Customer = @ls_order-customer
INTO @DATA(lv_name).
ENDLOOP.

With 1000 orders: 1000 SELECT statements!

Good (FOR ALL ENTRIES)

" One SELECT for all
SELECT Customer, CustomerName
FROM I_Customer
FOR ALL ENTRIES IN @lt_orders
WHERE Customer = @lt_orders-customer
INTO TABLE @DATA(lt_customers).
" Join in memory
LOOP AT lt_orders ASSIGNING FIELD-SYMBOL(<order>).
READ TABLE lt_customers INTO DATA(ls_cust)
WITH KEY customer = <order>-customer.
<order>-customer_name = ls_cust-customername.
ENDLOOP.

Speedup: ~90% (1000 -> 1 DB call)


3. CDS Views Instead of ABAP Joins

Bad (Join in ABAP)

SELECT Customer, CustomerName FROM I_Customer
INTO TABLE @DATA(lt_customers).
SELECT SalesOrder, Customer, NetValue FROM I_SalesOrder
INTO TABLE @DATA(lt_orders).
" Join in ABAP
LOOP AT lt_orders ASSIGNING <order>.
READ TABLE lt_customers INTO DATA(ls_cust)
WITH KEY customer = <order>-customer.
" ...
ENDLOOP.

Good (Join in CDS)

define view Z_CustomerOrders
as select from I_Customer
inner join I_SalesOrder
on I_Customer.Customer = I_SalesOrder.Customer
{
key I_Customer.Customer,
I_Customer.CustomerName,
I_SalesOrder.SalesOrder,
I_SalesOrder.NetValue
}
SELECT * FROM Z_CustomerOrders
INTO TABLE @DATA(lt_result).

Speedup: ~80% (DB does join more efficiently)


4. Batch EML Operations

Bad (Loop)

LOOP AT lt_book_ids INTO DATA(lv_id).
" MODIFY per ID
MODIFY ENTITIES OF zi_book IN LOCAL MODE
ENTITY Book
UPDATE FIELDS ( Status )
WITH VALUE #( ( BookId = lv_id Status = 'F' ) ).
ENDLOOP.
COMMIT ENTITIES.

With 100 books: 100x DB access!

Good (Batch)

" One MODIFY for all
MODIFY ENTITIES OF zi_book IN LOCAL MODE
ENTITY Book
UPDATE FIELDS ( Status )
WITH VALUE #( FOR lv_id IN lt_book_ids
( BookId = lv_id Status = 'F' ) )
FAILED DATA(failed).
COMMIT ENTITIES.

Speedup: ~85%


5. Projection Instead of SELECT *

Bad (all fields)

SELECT * FROM I_Product
INTO TABLE @DATA(lt_products).

Loads 50 fields, but only uses 3!

Good (only required fields)

SELECT Product, ProductName, Price
FROM I_Product
INTO TABLE @DATA(lt_products).

Speedup: ~60% (less network traffic)


6. Enable Table Buffering

For master data (rarely changes):

@AbapCatalog.buffering.status: #ACTIVE
@AbapCatalog.buffering.type: #FULL
@AbapCatalog.buffering.numberOfKeyFields: 1
define view Z_Country
as select from T005
{
key land1 as Country,
landx as CountryName
}

Speedup: ~95% (data from memory instead of DB)

BUT: Only for data that rarely changes!


7. FILTER Instead of LOOP + IF

Bad

DATA lt_active_customers TYPE TABLE OF ty_customer.
LOOP AT lt_customers INTO DATA(ls_customer)
WHERE status = 'ACTIVE'.
APPEND ls_customer TO lt_active_customers.
ENDLOOP.

Good (FILTER Expression)

DATA(lt_active) = FILTER #( lt_customers
WHERE status = 'ACTIVE' ).

Speedup: ~30% (less code, optimized)


8. REDUCE Instead of LOOP for Aggregations

Bad

DATA lv_total TYPE p.
LOOP AT lt_orders INTO DATA(ls_order).
lv_total = lv_total + ls_order-amount.
ENDLOOP.

Good (REDUCE)

DATA(lv_total) = REDUCE p( INIT sum = 0
FOR ls_order IN lt_orders
NEXT sum = sum + ls_order-amount ).

Speedup: ~20%


9. Lazy Loading with Associations

Bad (load everything)

define view Z_CustomerWithOrders
as select from I_Customer
left outer join I_SalesOrder
on I_Customer.Customer = I_SalesOrder.Customer
{
I_Customer.Customer,
I_Customer.CustomerName,
I_SalesOrder.SalesOrder,
I_SalesOrder.NetValue
}

Problem: Even when orders aren’t needed, always join!

Good (Association)

define view Z_Customer
as select from I_Customer
association [0..*] to I_SalesOrder as _Orders
on $projection.Customer = _Orders.Customer
{
key Customer,
CustomerName,
_Orders // Only expose, no join!
}

Usage:

" Only Customer
SELECT Customer, CustomerName
FROM Z_Customer
INTO TABLE @DATA(lt_customers).
" With Orders (only when needed!)
SELECT Customer, \_Orders-SalesOrder
FROM Z_Customer
INTO TABLE @DATA(lt_with_orders).

Speedup: ~70% (when orders are rarely needed)


10. Use SQL Trace

Find bottlenecks:

In ADT:

  1. Run -> Run Configurations
  2. Tab Trace Requests
  3. Enable SQL Trace
  4. Run program

Analyze:

SELECT * FROM mara
Duration: 2.5s
Rows: 500,000
SELECT matnr FROM mara
WHERE mtart = 'FERT'
Duration: 0.01s
Rows: 1,000

Action: Optimize slow SELECTs!


Performance Checklist

Code Review

  • No SELECT *
  • WHERE clause uses index
  • No SELECT in LOOP
  • EML batched
  • FOR ALL ENTRIES checks for empty table
  • CDS Views for joins
  • FILTER/REDUCE instead of LOOP
  • Buffering for master data

Measurement

  • SQL Trace performed
  • Performance < 1s for standard ops
  • No timeouts
  • Memory consumption acceptable

Performance Benchmarks

Example: 10,000 records

OperationBeforeAfterSpeedup
SELECT *2.5s0.3s (fields only)88%
SELECT in Loop15.0s0.5s (FOR ALL ENTRIES)97%
LOOP + IF0.8s0.2s (FILTER)75%
ABAP Join3.0s0.4s (CDS)87%
EML Loop5.0s0.6s (Batch)88%

Total: From 26.3s to 2.0s = 92% Speedup!


Summary

Quick Win Ranking:

  1. SELECT in Loop -> FOR ALL ENTRIES (+90%)
  2. EML Batching (+85%)
  3. Use WHERE clause (+95%)
  4. CDS Views for Joins (+80%)
  5. Only required fields (+60%)
  6. Lazy Loading (+70%)
  7. FILTER/REDUCE (+20-30%)
  8. Buffering (+95% but niche)
  9. SQL Trace (finds problems)
  10. Projection Views (+60%)

Mindset: Use DB power, minimize ABAP work!


See also:

Happy Optimizing!