DB - 토스뱅크 데이터 설계사상

데이터 모델링에 대한 토스의 생각 엿보기

Posted by Yan on December 31, 2021

토스 SLASH

중요한 것은 ‘고민을 하고 만들었는가’이다.

토스뱅크 데이터 설계사상

  1. 테이블의 통합과 분리
  2. 순환 참조 활용
  3. 테이블 종류의 체계적 관리
  4. 비대면 대량 거래 설계
  5. 성능 최적화 설계

1. 테이블의 통합과 분리

테이블을 분리한 경우

대출외부심사내역카드외부심사내역
  • 대출: 대출기본 - 대출외부심사내역 -> 신용평가사 KCB, CIS, NICE로 연계
  • 카드: 카드기본 - 카드외부심사내역 -> 신용평가사 KCB, CIS, NICE로 연계
  • 분리한 이유: 심사내역이 달라서 통합해서 사용하기 어려웠음

테이블을 통합하여 관리한 경우

대출/카드 연체원장
  • 대출/카드 연체원장 -> 경매/소송 기본 회생/파생 원장 신용회복원장
  • 통합한 이유: 연체금액, 연체일 등 공통적인 항목이 많았음.
    • 법적 절차 테이블은 고객별 데이터라서 통합하는 것이 더 효율적.
보증
  • 업무별: 심사, 청약, 보상
  • 상품별: 중금리, 마이너스, 스마트론, 햇살론, 전세보증
  • 기관별
  • 통합한 이유: 테이블이 너무 많아져서 통합의 필요성 대두

통합이 나은가? 분리가 나은가?

  • 통합: 여수신대출기본(여신), 수신계좌기본(수신)
  • 분리: 여신대출기본 수신대출기본 마이너스통장기본(여신) , 수신계좌기본(수신)

테이블 분리 원칙

  1. OneToOne Type : 개별 테이블
  • 개별 테이블로 접근이 많은 경우
  • 확장성 좋음
  • 조인성능 나쁨
  • I/O량 성능 좋음
  • 관리 용이성 떨어짐
  • 예시) 고객, 법인, 개인
  1. Plus Type: 슈퍼 + 서브 타입
  • 슈퍼 + 서브 형식으로 데이터를 처리하는 경우
  • 확장성 보통
  • 조인성능 나쁨
  • I/O량 성능 좋음
  • 관리 용이성 떨어짐
  • 예시) 법인고객, 개인고객
  1. Single Type: 단일 테이블
  • 전체를 일괄적으로 처리하는 경우
  • 확장성 나쁨
  • 조인성능 좋음
  • I/O량 성능 나쁨
  • 관리 용이성 높음
  • 예시) 고객

해법 : 공통분모를 최대한 가운데로 모으는 것

  • 데이터 양이 적으면 성능상 이슈가 없어서 최대한 통합하는 것이 좋다.
  • 데이터 양이 많으면 슈퍼/서브 테이블로 분리해야 한다.

2. 순환참조 활용

  • 순환참조는 자기 자신 테이블의 PK를 일반 속성으로 넣는 방식으로 설계한다.
  • START WITH..CONNECT BY 구문으로 선행 상태를 추적할 수 있다.
SELECT 여신관리번호
  FROM 여신관리테이블
  START WITH 여신관리번호 =: 여신관리번호
CONNECT BY PRIOR 이전여신관리번호 = 여신관리번호
  ORDER BY 여신관리등록일자

오라클 계층형 쿼리 START WITH..CONNECT BY

  • 계층형 구조: 상하 수직관계의 트리 형태 구조
  • 계층형 쿼리: 테이블에 저장된 데이터를 계층형 구조로 반환하는 쿼리
  • START WITH 조건 : 계층 구조가 어떤 행에서 시작하는지 지정하는 기능
    • 계층 질의의 루트(부모행)로 사용될 행을 지정
    • 서브쿼리를 사용할 수도 있다.
  • CONNET BY : 각 행이 어떻게 연결되는지. 계층구조 내에서 각 행의 관계 설정
    • PRIOR : 상위 행을 참조하는 것
    • CONNECT BY 직속상사 = PRIOR 직원 : 방금 전 행의 직원 값이 현재 행의 직속상사 값인 모든 행을 찾아라
    • 서브쿼리를 사용할 수 없다.
    • CONNECT BY PRIOR 자식 컬럼 = 부모 컬럼 : 부모 → 자식 순방향 전개
    • CONNECT BY PRIOR 부모 컬럼 = 자식 컬럼 : 자식 → 부모 역방향 전개
SELECT [컬럼]...
FROM [테이블]
WHERE [조건]
START WITH [최상위 조건]
CONNECT BY [PRIOR 계층형 구조 조건];

3. 테이블 종류의 체계적 관리

테이블 종류

  • Master Table : 원장성
  • Transactional Table : 거래성
  • History Table : 이력
  • Code Table
예시
  • 대출심사내역테이블에 종속된 대출심사이력테이블

  • 대출심사내역테이블 (Transaction Table)
    • 기준일자 PK
    • 고객번호 PK
    • 대출심사구분 PK
    • 평점
  • 대출심사이력테이블 (History Table)
    • 기준일자 PK
    • 고객번호 PK
    • 대출심사구분 PK
    • 이력일련번호 PK
    • 평점

4. 비대면 대량 거래 설계

계좌번호 대출신청번호, 금리산출번호 자리수 설계

  • 앞 3자리: 계정과목 코드
  • 마지막자리: check digit 코드

5. 성능 최적화 설계

채번

  • 오라클 시퀀스 -> 토스에서 사용
    • 장점: nextval로 사용하기 편하다. 가장 빠른 성능. 최소한의 Lock 발생한다.
    • 단점: 체계 부여가 불편하다. 빈 번호가 발생할 수 있다. 객체(시퀀스)가 증가한다.
INSERT INTO 대출기본
VALUES (시퀀스.nextval ...);
  • 채번 엔터티 -> 일반적으로 사용하던 방식
    • 장점: 순차적으로 엄격하게 채번한다. 체계적으로 채번한다(시퀀스보다 느리고 Max+1보다 빠름)
    • 단점: Lock사용으로 느린 채번. 객체(엔터티)가 증가한다.
SELECT no
FROM 채번테이블;

INSERT INTO 대출기본
VALUES(no ...);

UPDATE 채번테이블
SET no + 1;
  • Max+1
    • 장점: 별도의 객체가 필요하지 않다. 순차적으로 엄격하게 채번한다. 체계적인 채번이 가능하다.
    • 단점: Lock 사용으로 느린 채번. 예외 상황 발생 가능하다. 최대값 관리에 부담이 있다.
SELECT MAX(계좌번호)+1 no
FROM 대출기본;

INSERT INTO 대출기본
VALUES (no ...);

배치 대용량 처리

  • for loop 로직으로 DBMS를 여러차례 콜 하는 방식을 지양
  • 한 방 쿼리로 다 건 SELECT 해서 INSERT 하거나, MERGE문을 허용해서 DBMS를 1회만 콜 하도록 지향
MERGE INTO 내부직원 a
USING (
  SELECT 직원번호, 근무상태코드
  FROM 외부직원
  ) b
  ON(a.직원번호 = b.직원번호)
WHEN NOT MATCHED THEN
  INSERT (
    직원번호, 근무상태코드
  )
  VALUES (
    a.직원번호, b.근무상태코드
  )
WHEN MATCHED THEN
  UPDATE SET a.프레임워크변경타임스탬프 = current_timestamp
    a.WORK_STCD = b.근무상태코드
  • 필요에 따라 Partition Table, Parallel, Hint 적극 활용
  • Non-Partition: 논리적 1개, 물리적 1개일 경우 ex) 1월 ~ 5월
  • Partition: 논리적 1개, 물리적 5개일 경우 ex) 1월, 2월, 3월, 4월, 5월
reference

[Oracle] 오라클 계층형 쿼리(START WITH.. CONNECT BY)
토스뱅크 데이터 설계사상
오라클 계층쿼리 두번째!! CONNECT BY PRIOR
[Oracle]계층형 쿼리 사용법(START WITH, CONNECT BY PRIOR, ORDER SIBLINGS BY)