ABAP SQL 튜닝 시리즈 네 번째 글입니다. 실무에서 가장 자주 만나는 성능 문제가 이 편에 있습니다.
성능 리뷰에서 발견되면 거의 예외 없이 문제인 패턴입니다.
쿼리 하나하나는 빠릅니다. 인덱스도 탑니다. 그래서 더 위험합니다. ST05에서 개별 실행 시간만 보면 전혀 문제로 안 보입니다.
문제는 횟수입니다. 왕복 1건에 2ms라면 1만 건은 20초입니다. 이걸 N+1 문제라고 부릅니다.
ST05에서 SQL을 볼 때 동일한 쿼리가 반복 등장하는지를 먼저 확인하세요. 실행 시간 정렬만 보면 이 패턴은 절대 안 보입니다.
가장 무난한 방법입니다.
DB 접근 1번 + 메모리 조회 N번이 됩니다. HASHED TABLE은 건수가 늘어도 조회 속도가 거의 일정해서 이 용도에 적합합니다.
애초에 두 테이블을 함께 읽으면 되는 경우입니다.
FOR ALL ENTRIES(이하 FAE)는 편리하지만, 모르고 쓰면 사고가 나는 함정이 몇 개 있습니다. 하나씩 짚겠습니다.
lt_order가 비어 있으면 해당 WHERE 조건이 통째로 무시되어, 사실상 전건 조회가 됩니다.
FAE 앞에는 예외 없이 빈 테이블 체크를 답니다. 이건 선택이 아니라 규칙으로 삼는 편이 안전합니다.
이 함정은 평소엔 멀쩡하다가 특정 조건에서만 터집니다. 개발계 테스트 데이터로는 드라이버 테이블이 항상 채워져 문제가 안 보이다가, 운영에서 조회 결과가 0건인 날 갑자기 전건 조회가 나가는 식입니다.
FAE 결과에서는 선택한 필드 기준으로 중복 행이 제거됩니다. DISTINCT가 걸린 것처럼 동작합니다.
그래서 키 필드를 충분히 선택하지 않으면 행이 사라집니다.
"건수가 왜 이것밖에 안 나오지?" 하는 상황의 상당수가 이 원인입니다.
FAE를 쓰면 SAP 테이블 버퍼를 타지 않고 DB로 직행합니다. 버퍼링된 소량 마스터 테이블을 FAE로 읽으면, 버퍼를 두고도 매번 DB에 가는 셈입니다.
소량 코드성 테이블이라면 FAE 대신 전체를 한 번 읽어 내부 테이블에 두고 쓰는 편이 나을 수 있습니다.
FAE는 드라이버 테이블 내용을 조건으로 만들어 DB에 보내는데, 여러 번에 나눠 보냅니다. 드라이버에 중복이 많으면 불필요한 작업이 늘어납니다.
FAE가 한 번에 몇 건씩 묶어 보내는지는 시스템 프로파일 파라미터로 정해집니다. 이 값은 Basis 영역이므로, 개발자는 드라이버를 정리해 건수를 줄이는 쪽에 집중하면 됩니다.
S/4HANA에서는 JOIN 쪽이 유리한 경우가 많습니다. 조인 처리를 DB에서 하는 것이 ⑦편에서 다룰 Code-to-Data 방향과도 맞습니다.
다만 무조건은 아닙니다. 드라이버 데이터가 이미 ABAP에 있고 중간 가공이 필요하다면 FAE가 자연스럽습니다. 판단이 서지 않으면 양쪽을 다 만들어 ST05로 재보세요.
접근 횟수를 줄이는 또 다른 축입니다. 자주 읽고 거의 안 바뀌는 테이블은 애플리케이션 서버 메모리에 버퍼링해 두면 DB에 가지 않아도 됩니다.
주로 코드성·설정성 소량 테이블이 대상입니다. 버퍼링 설정 자체는 테이블 기술 설정에서 하지만, 개발자가 알아야 할 것은 어떤 SQL이 버퍼를 무력화하는지입니다.
| 버퍼를 우회하는 대표 사례 |
|---|
FOR ALL ENTRIES |
JOIN |
집계 함수 (SUM, COUNT 등), GROUP BY |
DISTINCT |
기본키가 아닌 ORDER BY |
| 서브쿼리 |
BYPASSING BUFFER 명시 |
버퍼링은 데이터가 자주 바뀌는 테이블에는 쓰면 안 됩니다. 버퍼 무효화 비용이 이득보다 커지고, 서버 간 동기화 지연으로 잠깐 옛 데이터를 볼 수도 있습니다. 트랜잭션 테이블에는 부적합합니다.
FOR ALL ENTRIES 3대 함정을 기억하세요.
다음 ⑤편부터는 대량 조회를 두 편에 걸쳐 다룹니다. 먼저 조회 속도, 즉 페이징입니다.
Disclaimer — 이 포스트는 AI(Claude)를 활용하여 작성된 초안을 바탕으로 검수 및 보완하여 작성되었습니다. 내용 중 오류나 오타가 있다면 댓글로 알려주시면 감사하겠습니다.