피드로 돌아가기
Dev.toDatabase
원문 읽기
N+1 Update 제거를 통한 처리 시간 4시간에서 8초로 단축
Set-Based Updates in Rails: 4 Hours to 8 Seconds
AI 요약
Context
ActiveRecord의 루프 내 개별 업데이트 방식으로 인한 N+1 Query 발생 상황. 50,000건의 데이터 처리 시 과도한 DB Transaction 생성으로 2GB RAM 소비 및 타임아웃 발생.
Technical Solution
- Application 레벨의 객체 로딩을 배제하고 Database 레벨에서 직접 연산을 수행하는 Set-Based Update 구조로 전환
update_all을 통한 단일 SQL UPDATE 구문 생성으로 네트워크 Round-trip 및 트랜잭션 오버헤드 최소화updated_at컬럼의 수동 갱신 설계를 통해 ActiveRecord Lifecycle 우회로 인한 캐시 무효화 실패 문제 해결in_batches를 활용한 데이터 분할 처리로 대량 업데이트 시 발생하는 Row Locking 시간 단축 및 동시성 확보CASE구문과sanitize_sql_array를 조합하여 개별 레코드별 서로 다른 값을 안전하고 효율적으로 업데이트하는 Heterogeneous Update 구현
Impact
- 데이터 처리 시간: 4시간 → 8초로 단축
- 페이지 로딩 속도: 20초 → 200ms로 개선 (View Count 증분 처리 기준)
Key Takeaway
비즈니스 로직 검증이나 콜백 실행이 불필요한 대량 데이터 변경 시에는 Application 중심의 객체 지향 업데이트보다 Database 중심의 집합 기반 업데이트가 압도적 성능을 제공함.
실천 포인트
- `.each` 루프 내부에서 `update` 호출 여부 확인 - `update_all` 사용 시 `updated_at` 수동 갱신 및 Callback 누락 여부 검토 - 대규모 업데이트 시 `in_batches` 적용을 통한 DB Lock 범위 제한 - 복합 값 업데이트 시 SQL Injection 방지를 위한 `sanitize_sql_array` 적용