ABAP SQL Rules That Still Matter on HANA
HANA being an in-memory columnar database does not eliminate the cost of a database round trip, and it does not fix a loop that issues a SELECT for every row of an internal table. The rules that still bite are: avoid SELECT inside a loop, filter on the database rather than in ABAP, avoid unnecessary SELECT *, and use FOR ALL ENTRIES or a JOIN correctly, because network hops and result set size still dominate response time.
Covers which classic ABAP database access rules survived the move to HANA and which ones changed, with the reasoning behind each. Focuses on the recurring production incident where code that ran acceptably on a small test system falls over on full data volume because the underlying access pattern was never actually fixed, only masked by a faster database.
Published 16 Sept 2026· 1,533 words
What it is
This is not a single object but a set of coding disciplines around Open SQL access that predate HANA and that many developers assume no longer apply because 'HANA is fast'. The structural fact that explains most of the confusion: HANA removes most of the cost of scanning and aggregating data inside the database engine, but it does nothing about the cost of the round trip between the ABAP application server and the database, and it does nothing about an ABAP program that fetches too much data and then filters, joins or aggregates it in ABAP instead of in SQL. A query that used to be slow because of a missing index can become fast on HANA for the wrong reason, while a query that issues one database call per loop iteration stays exactly as slow, because the bottleneck was never the engine, it was the number of calls.
When to use it
These rules apply to every piece of custom Open SQL in reports, function modules, class methods and CDS-based logic that touches transactional volume, not just batch jobs. They matter most in loops that read master or transaction data repeatedly, in interfaces that build result sets row by row, and in any code that was migrated from ECC without review. They matter less, though are still good practice, for one-off selection screens against small customizing tables or for code that runs once against a handful of rows. Reaching for a rewrite is a mistake when the object in question is already fast enough for its actual data volume and call frequency; chasing micro-optimizations on a report that runs twice a year against a few hundred rows wastes review time better spent on objects that run in the middle of an order-to-cash flow.
How it fits the stack
Below this sits the actual HANA database engine and its columnar storage, which rewards selective WHERE clauses and aggregation done inside SQL. Above it sits the ABAP application layer, including internal table processing, CDS views, AMDP procedures and native SQL, all of which are ways of expressing what gets pushed down versus what gets pulled up. These rules do not replace anything on their own; they are the discipline that decides whether code pushdown techniques such as CDS views or AMDP are used correctly or simply relocate a bad pattern from ABAP into SQL. Table buffering, which used to be a primary lever on ECC's disk-based database, is less central on HANA but still relevant for small, frequently read tables where avoiding a round trip beats avoiding a database scan.
A worked example
A billing report selects header records from VBRK into an internal table, then loops over that table and, for each header, issues a SELECT SINGLE against VBRP to fetch item totals, followed by another SELECT SINGLE against KNA1 for the customer name. On a development system with two hundred billing documents this runs in under a second. On production with two hundred thousand documents it takes twenty minutes and generates hundreds of thousands of individual database calls, each one paying the full round-trip cost regardless of how fast HANA itself is. The fix is not an index or a hint; it is restructuring the access. The header, item and customer data are pulled with a single JOIN or with FOR ALL ENTRIES against a distinct key list, sorted appropriately, with the aggregation for item totals done in the SQL statement rather than in an ABAP loop. The row count returned by the database does not change; the number of round trips drops from three per document to a small constant number for the whole run.
How to choose
- SELECT in a loop versus a single JOIN or FOR ALL ENTRIES: if the loop body issues a database call per iteration, that is almost always wrong past trivial row counts; the question to ask is whether the inner selection can be expressed as one statement with the outer key set.
- FOR ALL ENTRIES versus JOIN: FOR ALL ENTRIES requires an explicit check for an empty driver table, otherwise it silently selects the entire target table, and it implicitly deduplicates, which corrupts results if the caller expected one row per driver row; a JOIN avoids both traps but changes null handling for outer joins and needs care with multiple cardinality on the joined side.
- Filter in SQL versus filter in ABAP: any condition expressible in the WHERE clause belongs there; filtering a fully fetched internal table in ABAP after the fact means the database engine did wasted work and the network carried wasted rows.
- Aggregate in SQL versus aggregate in ABAP: SUM, COUNT, MAX pushed into the SELECT statement run inside the columnar engine and return one row instead of thousands; the same aggregation looped in ABAP after fetching detail rows is the pattern most often found in slow custom reports.
- Push to CDS or AMDP versus keep it in Open SQL: pushdown is worth the extra layer only when the logic is genuinely set-based and reusable; wrapping a row-by-row loop inside an AMDP procedure just moves the same anti-pattern into a place that is harder to review and outside standard ATC coverage in some checks.
- Buffer versus do not buffer: buffering still helps for small, read-heavy, rarely changed tables by avoiding the round trip entirely, but buffering large or volatile tables on HANA usually adds invalidation overhead for a scan the engine would have done fast anyway.
Common pitfalls
- Code tested against a few hundred rows in development passes review and then times out or locks up background work processes against full production volume, because the flaw was in the number of round trips, not in raw query speed, and small data sets never exposed it.
- FOR ALL ENTRIES called without checking that the driver table is non-empty, which returns the entire target table and is mistaken for a data problem rather than a coding defect.
- SELECT * retained out of habit on wide tables, pulling long text or raw fields across the network for every row when only two or three fields are used downstream.
- Aggregation done in ABAP after fetching full detail because the original ECC-era code predates confidence in database-side aggregate functions, left unchanged during a lift-and-shift conversion.
- Assuming that because the database is now HANA, no further tuning is needed, so a genuinely bad access pattern ships to production unreviewed and only surfaces as a short dump or a locked work process weeks after go-live.
- Native SQL or AMDP used to hand-optimize a query in a way that bypasses Open SQL's authorization and buffering behavior, creating a maintenance and clean core problem that outlives the performance win it was meant to buy.
ECC, S/4HANA and clean core
On S/4HANA these rules are enforced more visibly than on ECC because custom code checks run as part of conversion projects flag exactly this class of pattern: SELECT in a loop, missing WHERE conditions, unchecked FOR ALL ENTRIES. Code pushdown through CDS views and AMDP is the sanctioned way to move genuinely set-based logic closer to the data, but under a clean core approach, native SQL and direct table access outside the released API surface are discouraged, and custom logic that needs pushdown should prefer CDS or the extensibility framework rather than hand-written native SQL scattered through custom reports. The rules themselves have not changed; what has changed is that they now surface as concrete findings during a conversion rather than as vague complaints about a slow report.
Whose problem this is
This is developer territory during coding and code review, with an architect involved only when a decision is made to push logic into CDS or AMDP for a shared, high-traffic object. Handover to functional teams should include realistic production-scale test data, since the whole class of defect described here is invisible against small data sets and only shows up under load.
Related SAP objects
Reviewed pages this object connects to in the ERPClimb knowledge graph.
Source: ERPClimb — https://erpclimb.com/sap-technical-topics/abap-sql-performance-rules-that-still-matter-on-hanaERPClimb is an independent platform and is not affiliated with SAP SE. Reference pages are written and reviewed by SAP consultants for learning and troubleshooting.