HANA Cursor 금지 — Set 전환 3가지 이유 #shorts #SAP #HANA
아직도 커서로 한 줄씩 도세요?
SAP HANA는 컬럼 스토어 기반의 인메모리 DB입니다. 한 번의 SQL로 수백만 건을 동시에 훑어내도록 설계되었죠. 그런데 ABAP/PL/SQL 시절 습관 그대로 OPEN CURSOR ... FETCH로 한 행씩 끄집어내 처리하면, HANA의 병렬 엔진은 사실상 놀게 됩니다. 행 하나마다 컨텍스트 스위칭과 결과셋 직렬화가 발생하기 때문에, 같은 로직이 수십 배 느려지는 일도 흔합니다.
Cursor가 느린 진짜 이유
커서는 본질적으로 OLTP의 행 지향 사고방식입니다. HANA의 SQLScript Optimizer는 절차형 루프를 만나는 순간 식별 가능한 세트 연산이 끊어지면서 plan vectorization이 깨집니다. 결과적으로 컬럼 스토어의 SIMD 처리, 파티션 병렬화, 조인 엔진의 hash/range 최적화를 거의 활용하지 못하고, 메인 스레드에서 직렬로 도는 모양새가 됩니다.
- 매 FETCH마다 결과 패키징 오버헤드 발생
- 중간 변수 할당으로 인해 옵티마이저의 식별/푸시다운 실패
- 병렬 실행 단위(JE/CE) 비활성, 단일 스레드 처리
- 대용량에서 트랜잭션 로그 및 락 점유 시간 증가
안티패턴 vs Set-based
예를 들어 매출 테이블에서 할인 등급별로 보너스를 갱신하는 시나리오를 봅니다. 커서로 풀면 익숙하지만 HANA에선 비효율입니다.
-- 안티패턴: 행 단위 커서 처리
DO BEGIN
DECLARE CURSOR c_sales FOR
SELECT order_id, amount FROM sales WHERE status = 'OPEN';
FOR row AS c_sales DO
IF :row.amount >= 10000 THEN
UPDATE sales SET bonus = :row.amount * 0.05
WHERE order_id = :row.order_id;
ELSE
UPDATE sales SET bonus = :row.amount * 0.01
WHERE order_id = :row.order_id;
END IF;
END FOR;
END;
같은 로직을 단일 SET 연산으로 바꾸면 옵티마이저가 컬럼 스캔 한 번에 처리합니다.
-- 권장: Set-based 단일 UPDATE
UPDATE sales
SET bonus = CASE
WHEN amount >= 10000 THEN amount * 0.05
ELSE amount * 0.01
END
WHERE status = 'OPEN';
실제 벤치마크에서는 수십만 건 기준 커서 대비 10~100배 수준의 응답 시간 단축이 보고되는 경우가 일반적입니다. 복잡한 분기 로직이라면 MERGE INTO나 테이블 변수(TABLE 타입) 기반 일괄 처리도 권장됩니다.
언제까지 커서를 써도 될까
아주 작은 마스터 데이터의 순서 의존 처리, 외부 API 호출처럼 본질적으로 직렬일 때만 제한적으로 사용합니다. 대용량 트랜잭션·집계·갱신은 SET 기반 SQL, 또는 SQLScript의 테이블 변수 파이프라인으로 재작성하는 것이 일반적인 권장 패턴입니다.
핵심 한 줄
HANA에서 커서는 안티패턴, 한 줄씩 돌리지 말고 한 문장으로 처리하세요.