토스 SLASH
중요한 것은 ‘고민을 하고 만들었는가’이다.
토스뱅크 데이터 설계사상
- 테이블의 통합과 분리
- 순환 참조 활용
- 테이블 종류의 체계적 관리
- 비대면 대량 거래 설계
- 성능 최적화 설계
1. 테이블의 통합과 분리
테이블을 분리한 경우
대출외부심사내역
과 카드외부심사내역
- 대출:
대출기본
-대출외부심사내역
-> 신용평가사 KCB, CIS, NICE로 연계 - 카드:
카드기본
-카드외부심사내역
-> 신용평가사 KCB, CIS, NICE로 연계 - 분리한 이유: 심사내역이 달라서 통합해서 사용하기 어려웠음
테이블을 통합하여 관리한 경우
대출/카드 연체원장
-
대출/카드 연체원장
->경매/소송 기본
회생/파생 원장
신용회복원장
- 통합한 이유: 연체금액, 연체일 등 공통적인 항목이 많았음.
- 법적 절차 테이블은 고객별 데이터라서 통합하는 것이 더 효율적.
보증
- 업무별:
심사
,청약
,보상
- 상품별:
중금리
,마이너스
,스마트론
,햇살론
,전세보증
등 - 기관별
- 통합한 이유: 테이블이 너무 많아져서 통합의 필요성 대두
통합이 나은가? 분리가 나은가?
- 통합:
여수신대출기본
(여신),수신계좌기본
(수신) -
분리: 여신대출기본
수신대출기본
마이너스통장기본
(여신) ,수신계좌기본
(수신)
테이블 분리 원칙
- OneToOne Type : 개별 테이블
- 개별 테이블로 접근이 많은 경우
- 확장성 좋음
- 조인성능 나쁨
- I/O량 성능 좋음
- 관리 용이성 떨어짐
- 예시)
고객
,법인
,개인
- Plus Type: 슈퍼 + 서브 타입
- 슈퍼 + 서브 형식으로 데이터를 처리하는 경우
- 확장성 보통
- 조인성능 나쁨
- I/O량 성능 좋음
- 관리 용이성 떨어짐
- 예시)
법인고객
,개인고객
- 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)