JOIN을 지웠더니 편안해졌다, Application-Level Join 실전 도입기
·
탐구 생활/데이터베이스
이전 글에서는 RDBMS 조인이 '넓은 테이블(Wide Table)'과 '깊은 페이지네이션(Deep Pagination)'을 만났을 때 겪게 되는 수학적, 아키텍처적 한계와 디스크 스필(Disk Spill) 현상을 다루었습니다. 이 글에서는 디스크 스필이 실제 프로덕션 환경에서 어떻게 시스템 장애를 유발했는지, 그리고 이를 어플리케이션 레벨 조인(Application-Level Join)이라는 설계 패턴으로 어떻게 타파했는지 공유합니다.장애의 발단제가 맡은 서비스는 간혹 데이터베이스 CPU사용률이 80~90%까지 치솟는 문제가 발생하고 있었습니다. 이때마다 Read Instance가 수평확장되어서 결국 서비스가 안정화 되었지만, Read Instance가 확장되고 안정화되고 백엔드 어플리케이션과 연결될때..
MySQL vs PostgreSQL, 조인의 불확실성과 엔진별 한계
·
탐구 생활/데이터베이스
ORM이 보편화되면서 백엔드 개발자들은 select_related나 joinedload(JPA에서는 JOIN FETCH)를 통해 손쉽게 두 테이블을 INNER JOIN으로 엮어냅니다. 그리고 "옵티마이저가 알아서 쿼리를 최적화하여 필요한 데이터만 조인하겠지"라고 기대합니다. 하지만 데이터베이스가 감당해야 할 데이터가 수백만 건을 넘어가고, 넓은(Wide) 테이블에 깊은 페이지네이션(Deep Pagination)이 결합하는 순간 이 기대는 처참히 무너집니다. 이 글에서는 PostgreSQL과 MySQL(InnoDB)의 내부 아키텍처를 바탕으로, RDBMS 조인이 태생적으로 안고 있는 구조적 한계와 알고리즘의 맹점을 이론적으로 분석해 봅니다.관계 대수의 제약과 의미론적 장벽(Semantic Barrier)P..
MySQL vs PostgreSQL 2편: UPDATE의 나비효과
·
탐구 생활/데이터베이스
MySQL vs PostgreSQL 1편에서는 MySQL의 Index-Organized Table(IOT)과 PostgreSQL의 Heap Table 구조를 비교하며, 데이터를 저장하고 읽는(Read) 방식의 근본적인 차이를 알아보았습니다. PostgreSQL은 무거운 데이터를 억지로 정렬하지 않고 힙(Heap) 공간에 마구잡이로 던져 넣은 뒤, 인덱스에서 물리적 주소(TID)로 다이렉트로 꽂아버리는 방식을 택했습니다. 읽기(Read) 관점에서는 트리를 두 번 타야 하는 MySQL보다 구조적으로 훨씬 명쾌하고 빨라 보였죠. 하지만 데이터베이스의 진짜 숙명은 조회가 아니라 끊임없는 '변경(UPDATE)'에 있습니다. 오늘은 데이터가 변경되는 순간, 평화롭던 PostgreSQL의 힙 구조에 어떤 거대한 나비..