client/media/skills/abap-performance-hana/SKILL.md
--- name: abap-performance-hana description: ABAP performance best practices for S/4HANA and HANA database systems.Use when writing or reviewing ABAP code on HANA-based systems.IMPORTANT: First use the SAP system info tool to check the system type — if the system is ECC or runs on a traditional database (Oracle, DB2, MSSQL), load the abap-performance-ecc skill instead. Covers code pushdown, CDS views, AMDP, advanced SQL, and HANA-optimized patterns. argument-hint: '[ABAP code to optimize on HANA
npx skillsauth add marcellourbani/vscode_abap_remote_fs client/media/skills/abap-performance-hanaInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
These rules apply to SAP S/4HANA systems or any ABAP system running on HANA DB.
Before using this skill: Call the SAP system info tool. If the system is ECC on a traditional DB, use the abap-performance-ecc skill instead.
Core philosophy on HANA: Push data-intensive operations to the database. HANA is a columnar in-memory DB optimized for set-based operations, aggregations, and complex SQL. Let it do the heavy lifting. Keep ABAP for business logic, authorization, and exception handling.
Move data-intensive operations to the database layer.
Select only the fields you need. Never SELECT * in production.
SELECT matnr, maktx FROM mara INTO TABLE @DATA(itab).
Always use a WHERE clause. Always use @ escaped host variables.
Use JOINs aggressively — HANA handles complex JOINs very well, even 5+ tables.
SELECT m~matnr, t~maktx, p~werks, p~ekgrp
FROM mara AS m
INNER JOIN makt AS t ON t~matnr = m~matnr AND t~spras = @sy-langu
INNER JOIN marc AS p ON p~matnr = m~matnr
LEFT OUTER JOIN mvke AS s ON s~matnr = m~matnr
WHERE m~mtart = @material_type
INTO TABLE @DATA(materials).
Use aggregate functions and GROUP BY — let HANA calculate:
SELECT werks, SUM( labst ) AS total_stock, COUNT(*) AS item_count
FROM mard
WHERE matnr = @matnr
GROUP BY werks
INTO TABLE @DATA(stock_by_plant).
Use CASE expressions to push conditional logic to the DB:
SELECT matnr,
CASE mtart
WHEN 'FERT' THEN 'Finished'
WHEN 'ROH' THEN 'Raw Material'
ELSE 'Other'
END AS type_text
FROM mara
INTO TABLE @DATA(materials).
Use string functions in SQL:
SELECT matnr, CONCAT( matnr, CONCAT( ' - ', maktx ) ) AS display_text
FROM mara
INNER JOIN makt ON makt~matnr = mara~matnr AND makt~spras = @sy-langu
INTO TABLE @DATA(display_data).
Use FOR ALL ENTRIES when JOINs aren't possible. Always check driver table is not empty.
Use UP TO n ROWS when you only need limited results.
Use subqueries where they simplify logic:
SELECT matnr, maktx FROM mara
WHERE matnr IN ( SELECT matnr FROM marc WHERE werks = @plant )
INTO TABLE @DATA(plant_materials).
SELECT FROM zcds_view.Never SELECT the same data twice. Read once, reuse.
Use READ TABLE on internal table buffer instead of SELECT SINGLE in a loop:
SELECT matnr, maktx FROM makt WHERE spras = @sy-langu INTO TABLE @DATA(texts).
" later:
READ TABLE texts WITH KEY matnr = current_matnr INTO DATA(text_line).
On HANA, even redundant DB access is faster than on traditional DBs — but it's still wasteful and adds network overhead.
Buffering matters less on HANA than ECC because HANA is in-memory. But it still helps for:
Reducing network round-trips between app server and DB server
Avoiding query parsing overhead for tiny lookups
Use SELECT SINGLE on buffered tables — reads from buffer. UP TO 1 ROWS bypasses buffer.
" good — uses buffer
SELECT SINGLE * FROM t001 WHERE bukrs = @bukrs INTO @DATA(company).
" bad — bypasses buffer
SELECT * FROM t001 UP TO 1 ROWS WHERE bukrs = @bukrs INTO @DATA(company).
JOINs, aggregates, GROUP BY, ORDER BY, subqueries bypass the buffer.
Same rules as any ABAP system — this is ABAP runtime, not DB:
" good — O(1) lookup
DATA materials TYPE HASHED TABLE OF mara WITH UNIQUE KEY matnr.
READ TABLE materials WITH TABLE KEY matnr = input INTO DATA(mat).
ASSIGNING FIELD-SYMBOL(<fs>) for fastest loop processing.WHERE on LOOP — especially on SORTED tables.FILTER for extracting subsets from SORTED/HASHED tables:
DATA(subset) = FILTER #( sorted_table WHERE status = 'A' ).
INSERT lines_of for bulk inserts.VALUE #( FOR ... ) and REDUCE for functional transformations.CORRESPONDING #( ) for structure mapping.Before writing a complex ABAP loop with aggregation, filtering, or transformation — ask: can this be a SQL statement instead?
" ABAP way (acceptable for small data)
LOOP AT sales ASSIGNING FIELD-SYMBOL(<s>).
AT NEW kunnr.
total = 0.
ENDAT.
total += <s>-netwr.
AT END OF kunnr.
APPEND VALUE #( kunnr = <s>-kunnr total = total ) TO totals.
ENDAT.
ENDLOOP.
" HANA way (better for large data)
SELECT kunnr, SUM( netwr ) AS total
FROM vbak
WHERE erdat >= @from_date
GROUP BY kunnr
INTO TABLE @DATA(totals).
Use string templates | | instead of CONCATENATE.
Avoid repeated string concatenation in loops — build a string table:
DATA lines TYPE string_table.
LOOP AT data INTO DATA(d).
APPEND |{ d-field1 };{ d-field2 }| TO lines.
ENDLOOP.
DATA(csv) = concat_lines_of( table = lines sep = cl_abap_char_utilities=>cr_lf ).
HANA-specific: For heavy string assembly from DB data, consider doing it in SQL with CONCAT or STRING_AGG (via CDS/AMDP).
Check authority before expensive data retrieval:
AUTHORITY-CHECK OBJECT 'M_MATE_WRK' ID 'WERKS' FIELD plant.
IF sy-subrc <> 0. RAISE EXCEPTION NEW zcx_no_auth( ). ENDIF.
SELECT ... " now fetch
On S/4HANA, consider CDS access control (DCL) for row-level authorization built into the data model.
CL_SALV_TABLE for read-only display.aRFC for independent parallel tasks.SPTA framework for parallelized mass processing.| Anti-Pattern | Fix |
|---|---|
| SELECT * | Select only needed fields |
| SELECT in a LOOP | JOINs (HANA handles complex JOINs well) |
| Aggregating in ABAP loops | SUM/COUNT/AVG in SQL with GROUP BY |
| Filtering in ABAP what SQL can filter | Push WHERE to SQL |
| Multiple SELECTs that could be one JOIN | Combine into single JOIN statement |
| Nested LOOPs on STANDARD tables | HASHED lookup for inner data |
| Complex ABAP transformations on large data | CDS view or AMDP |
| String concat in loops with && | Build string table, or push to SQL |
| Ignoring CDS views | Use CDS for reusable data models |
| UP TO 1 ROWS on buffered table | SELECT SINGLE to use buffer |
| Authority check after data retrieval | Check before SELECT, or use CDS DCL |
| Writing ABAP for what SQL can express | Push to database — always ask "can SQL do this?" |
development
Create SAP Data Workbooks (.sapwb) for SAP data analysis. Use when the user asks to analyze SAP data, create data quality checks, build reports, compare tables, profile data, or any multi-step SAP data exploration. Workbooks have ABAP SQL cells (queries against SAP) and JavaScript cells (process results). They save as files and can be re-run.
tools
Investigate SAP ADT REST API endpoints. Use when the user asks about ADT API endpoints, request/response XML formats, content types, or how a specific ADT feature works under the hood. Teaches how to trace from discovery documents → RES_APP classes → handler classes → Simple Transformations → XML schemas. Requires the adt_discovery_export tool output files and standard ABAP tools (get_abap_object_lines, search_abap_objects, search_abap_object_lines).
development
Generate a comprehensive SAP System Personality Report. Analyzes custom code landscape, functional footprint, development activity, health metrics, and package breakdown. Use when a user asks to characterize a system, understand a system, get a system overview, system report, system personality, or "what does this system do?" Collects data via SQL queries and presents results in a structured webview.
data-ai
Navigate and understand SAP Customizing (SPRO/IMG). Use when the user asks about customizing settings, SPRO activities, configuration tables, maintenance views, view clusters, or needs to read/understand any customizing data. This skill teaches how to systematically trace from an SPRO activity to the actual tables where config data is stored, and how to find the SPRO menu path for any activity. Load this skill whenever customizing, SPRO, IMG, configuration, or settings maintenance is involved.