Lock은 데이터베이스 특징을 결정짓는 가장 핵심적인 메커니즘

 

오라클 Lock

공유 리소스와 사용자 데이터를 보호할 목적으로 다양한 종류의 Lock을 사용한다.

  • DML Lock : 다중 트랜잭션이 동시에 액세스하는 사용자 데이터의 무결성 보호
    • 테이블 Lock
    • 로우 Lock
  • DDL Lock
  • 래치 : SGA에 공유된 각종 자료구조를 보호하기 위해 사용됨
  • 버퍼 Lock : 버퍼 블록에 대한 액세스를 직렬화하기 위해 사용
  • 라이브러리 캐시 Lock/Pin : 캐시에 공유된 SQL 커서와 PL/SQL 프로그램을 보호하기 위해 사용

 

DML Lock

  • 로우 Lock : 두 개의 동시 트랜잭션이 같은 로우를 변경하는 것을 방지 -> 하나의 로우를 변경하려면 로우 Lock 먼저 설정
    • DML 로우 Lock 에는 베타적 모드를 사용하므로 UPDATE 또는 DELETE를 진행중인 로우를 다른 트랜잭션이 UPDATE 하거나 DELETE할 수 없다.
    • INSERT에 대한 로우 Lock 경합은 Unique 인덱스가 있을 때만 발생한다. 즉 Unique 인덱스가 있는 상황에서 두 트랜잭션이 같은 값을 입력하라고 할때 블로킹이 발생한다. 블로킹이 발생하면 후행 트랜잭션은 기다렸다가 선행 트랜잭션이 커밋하면 INSERT에 실패하고 롤백하면 성공한다. 두 트랜잭션이 서로 다른 값을 입려갛거나 Unique 인덱스가 아예 없으면 INSERT에 대한 로우 Lock 경합은 발생하지 않는다.
    • MVCC 모델을 사용하는 오라클은 SELETE 문에 로우 Lock을 사용하지 않는다. 오라클은 다른 트랜잭션이 변경한 로우를 읽을 때 복사본 블록을 만들어서 쿼리가 시작된 시점으로 되돌려서 읽는다. 변경이 진행 중인 로우를 읽을 때도 Lock이 풀릴때까지 기다리지 않고 복사본을 만들어서 읽는다. 따라서 SELECT 문에 Lock을 사용할 필요가 없다.
    • 즉 오라클에서는 DML과 SELECT는 서로 진행을 방해하지 않는다. 물론 SELECT끼리도 서로 방해하지않는다. DML끼리는 서로 방해할 수 있다.
    • MVCC 모델을 사용하지 않는 DbMS는 SELECT문에 공유 Lock을 사용한다. 공유 Lock끼리는 호환된다. 두 트랜잭션이 같은 Lock을 설정할 수 있다는 뜻이다. 공유 Lock과 배타적 Lock은 호환되지 않기 떄문에 DML과 SELECT가 서로 진행을 방해할 수 있다. 즉 다른 트랜잭션이 읽고 있는 로우를 변경하려면 다음 레코드로 이동할 때까지 기다려야하고, 다른 트랜잭션이 ㅂ녀경중인 로우를 읽으려면 커밋할때까지 기다려야한다.
    • DML 로우 Lock에 의한 성능 저하를 방지하려면 OLTP를 처리하는 주간에 Lock을 필요 이상으로 오래 유지않도록 커밋 시점을 조절해야한다. 그에 앞서 트랜잭션이 빨리 일을 마치도록 관련 SQL을 튜닝해야한다.
     
  • DML 테이블 Lock (TM Lock)
    • 로우 Lock을 설정하기전에 테이블 Lock을 먼저 설정한다. 현재 트랜잭션이 갱신중인 테이블 구조를 다른 트랜잭션이 변경하지 못하게 막기 위해서다.
    • 로우 Lock은 항상 배타적 모드를 사용하지만 테이블 Lock에는 여러 가지 Lock 모드를 사용한다. 아래 표는 모드간 호환성을 정리한것이다. 

RS : row share(SS sub share), RX : row excluesive (SX), S : share, SRX : share row exclusice, X

  • -
    •  INSERT, UPDATE, DELETE, MERGE문을 위해 로우 Lock을 설정하려면 해당 테이블에 RX 모드 테이블 Lock을 먼저 설정해야한다.
    • SELECT FOR UPDATE문은 10gR1 -> RS, 10gR2이상 -> RX 모드 설정
    • RS, RX 간에는 어떤 조합으로도 호환되므로 SELECT FRO UPDATE나 DML문 수행시 테이블 Lock에 의한 경험은 발생하지 않는다. 같은 로우를 갱신하려고 할때만 로우 Lock에 의한 경합이 발생한다.
    • 즉 테이블 Lock은 테이블 Lock을 설정한 트랜잭션이 해당 테이블에서 현재 어떤 작업을 수행 중인지 알리는 일종의 푯말이다. 그래서 어떤 모드를 사용했는지에 따라 후행 트랜잭션이 수행할 수 있는 작업의 범위가 결정된다.

COMMIT

  • 블로킹 : 선행 트랜잭션이 설정한 Lock 때문에 후행 트랜잭션이 작업을 진행하지 못하고 멈춰있는 상태 -> 해결하려면 커밋
  • 교착상태 : 두 트랜잭션이 특정 리소스에 Lock을 설정한 상태에서 맞은편 트랜잭션이 Lock을 설정한 리소스에 또 Lock을 설정하려고 진행하는 상황을 말한다.

교착상태를 발생시킨 문장 하나만 롤백하는것

이 메시지를 받은 트랜잭션은 커밋 또는 롤백을 결정해야한다. 이것은 예외처리안하면 대기 상태 지속된다.

 

불필요하게 트랜잭션을 길게 정의하지 않도록 주의해야한다.

  • Undo 세그먼트 고갈
  • Undo 세그먼트 경합 유발

DML Lcok 때문에 동시성이 저하되지 않도록 적절한 시점에 커밋해야한다.

너무 커밋이 자주 발새앟면

  • 서버 프로세스가 LGWR에게 로그 버퍼를 비우도록 요청하고 동기방식으로 기다리는 횟수 증가 -> 성능 느려짐
  • 10gW2부터 제공하는 비동기식 커밋과 배치 커밋 활용 방안 검토

파티션을 활용한 대량 UPDATE 튜닝

대량 데이터를 입력/수정/삭제할때는 인덱스를 Drop하거나 Unusable 상태로 변경하고서 작업하는 방법을 많이 활용한다. 손익 분기점은 5%정도로 본다. 즉 입력/수정/삭제하는 데이터 비중이 5%를 넘는다면, 인덱스를 그대로 둔 상태에서 작업하기보다 인덱스 없이 작업한 후에 재생성하는 것이 빠르다는 뜻이다.

 

근데 일부 건을 위해 대량 데이터를 인덱스를 재 생성하는 것은 부담된다.

 

파티션 Exchange를 이용한 대량 데이터 변경

테이블이 파티셔닝돼 있고 인덱스도 다행히 로컬 파티션이라면 수정된 값을 갖는 임시 세스먼트를 만들어 원본 파티션과 바꿔치기하는 방식이다.

  1. 임시테이블을 생성한다. 할수있다면 nologging모드로 생성한다.
  2. 거래 데이터를 읽어 임시 테이블에 입력하면서 상태코드 값을 수정한다.
  3. 임시 테이블에 원본 테이블과 같은 구조로 인덱스를 생성한다. 할수있다면 nologging 모드로 생성한다.
  4. 파티션과 임시테이블을 Exchange 한다.
  5. 임시테이블을 Drop한다.
  6. (nologging 모드로 작업했다면) 파티션을 logging 모드로 전환한다.

 

파티션을 활용한 대량 DELETE 튜닝

초대용량 테이블 인덱스를 Drop했다가 다시 생성하기도 쉽지않다.

 

파티션 Drop을 이용한 대량 데이터 삭제

테이블이 삭제 조건절 컬럼 기준으로 파티셔닝돼있고 인덱스도 로컬 파티션이라면

파티션 Truncate를 이용한 대량 데이터 삭제

거래일자 조건에 해당하는 데이터를 일괄 삭제하지 않고 아래와 같이 또 다른 삭제 조건이 있는 경우. (상태코드 <> 'ㅇㅇㅇ' 상태코드 is null) 조건을 만족하는 데이터가 소수이면 DELETE문을 그대로 사용하면 된다.

만약 소수가 아니라 대다수이면 남길 데이터만 백업했다가 재입력하는 방식이 빠르다

  1. 임시 테이블을 생성하고 남길 데이터만 복제한다.
  2. 삭제 대상 테이블 파티션을 Truncate한다.
  3. 임시테이블에 복제해 둔 데이터를 원본 테이블에 입력한다.
  4. 임시 테이블을 Drop한다.

 

파티션을 활용한 대량 INSERT 튜닝

비파티션 테이블일때

 

파티션 테이블일때

'SQLP > SQLP' 카테고리의 다른 글

6-4. Lock과 트랜잭션 동시성 제어 (2)  (0) 2025.02.23
6-4. Lock과 트랜잭션 동시성 제어  (0) 2025.02.23
6.3 파티션을 활용한 DML 튜닝 (1)  (0) 2025.02.22
6-1, DML 기본 튜닝 (2)  (0) 2025.02.21
6-1. 기본 DML 튜닝 (1)  (0) 2025.02.20

파티션을 이용하면 대량 추가/변경/삭제 작업을 빠르게 처리할 수 있다.

 

테이블 파티션

파티셔닝은 테이블 또는 인덱스 데이터를 특정 컬럼 값에 따라 별도 세그먼트에 나눠서 저장하는 것을 말한다.

  • 관리적 측면 : 파티션 단위 백업, 추가, 삭제, 변경 -> 가용성 향상
  • 성능적 측면 : 파티션 단위 조회 및 DML, 경합 또는 부하 분산

파티션에는 Range, 해시, 리스트가 있다.

Range 파티션

가장 기초적인 방식으로 주로 날짜 컬럼을 기준으로 파티셔닝한다.

위와 같은 파티션 테이블에 값을 입력하면 각 레코드가 파티션 키값에 따라 분할 저장하고 읽을때도 검색 조건을 만족하는 파티션만 골라 읽을 수 있어 이력성 데이터를 Full Scan 방식으로 조회할 때 성능을 크게 향상한다. 보관주기 정책에 따라 과거 데이터가 저장된 파티션만 백업하고 삭제하는 등 데이터 관리 작업을 효율적이고 빠르게 수행할 수 있는 장점도 있다.

 

파티션 테이블에 대한 SQL 성능 향상 원리는 파티션 Pruning(Elimination)에 있다. prune은 쓸데없는 가지를 치다라는 뜻을 가지는데 

즉 파티션 Pruning은 SQL 하드파싱이나 실행 시점에 조건절을 분석해서 읽지 않아도 되는 파티션 세그먼트를 액세스 대상에서 제외하는 기능이다.

위 SQL의 조건절을 만족하는 데이터는 1200만건중 25%에 해당하는 300만건이다. 인덱스로 건건이 랜덤 액세스하면 테이블 전체를 스캔하는 것보다 느리다. 하지만 테이블 전체를 스캔하자니 사이즈가 너무 크다.

 

오른쪽처럼 100만건 단위로 나눠서 저장하면, Full Scan 하더라도 전체가 아닌 일부 파티션 세그먼트만 읽고 멈출 수 있어 성능이 향상된다. 파티션 과 병렬 처리가 만나면 더 효가가 좋다.

화살표로 표현한 것처럼 파티션 테이블도 인덱스로 액세스할 수 있지만, 파티션 Pruning을 이용한 테이블 스캔보다 훨씬 느린다.

파티션도 클러스터 IOT와 마찬가지로 관련 있는 데이터가 흩어지지 않고 물리적으로 인접하도록 저장하는 클러스터링 기술에 속한다. 클러스터와 다른점은 세그먼트 단위로 모아서 저장한다는 것이다.

 

해시 파티션

파티션 키 값을 해시 함수에 입력해서 반환받은 값이 같은 데이터를 같은 세그먼트에 저장하는 방식

파티션 개수만 사용자가 결정하고 데이터를 분산하는 알고리즘은 오라클 내부 해시함수가 결정

해시파티션은 고객ID처럼 변별력이 좋고 데이터 분포가 고른 컬럼을 파티션 기준으로 선정해야 효과적

검색할 때는 조건절 비교 값에 똑같은 해시 함수를 적용함으로써 읽을 파티션을 결정한다. 해시 알고리즘 특성상 등치 조건 또는 IN-LIST 조건으로 검색할 때만 파티션 Pruning이 작동한다.

 

리스트 파티션

사용자가 정의한 그룹핑 기준에 따라 데이터를 분할 저장하는 방식이다.

Range 파티션에선 값의 순서에 따라 저장할 파티션이 결정되지만, 리스트 파티션에서는 순서와 상관없이 불연속적인 값의 목록에 의해 결정된다.

해시 파티션과 비교하면 해시 파티션은 오라클이 정한 해시 알고리즘에 따라 임의로 분할하는 반면, 리스트 파티션은 사용자가 정의한 논리적인 그룹에 따라 분할. 업무적인 친화도에 따라 그룹핑 기준을 정하되, 될 수 있으면 각 파티션에 값이 고르게 분산되도록 해야한다

 

인덱스 파티션

  • 테이블 파티션
    • 비파티션 테이블
    • 파티션 테이블
  • 인덱스 (파티션, 비파티션)
    • 로컬 파티션 인덱스 : 
    • 글로벌 파티션 인덱스
    • 비파티션 인덱스

로컬 파티션 인덱스는 테이블 파티션과 인덱스 파티션이 서로 1:1 대응 관계가 되도록 오라클이 자동으로 관리하는 파티션 인덱스를 말한다. 로컬이 아닌 파티션 인덱스는 '모두' 글로벌 파티션 인덱스이며, 테이블 파티션과 독립적인 구성(파티션 키, 파티션 기준값 정의)을 갖는다.

 

로컬 파티션 인덱스

뒤에 LOCAL 옵션을 추가하면 된다.

각 인덱스 파티션은 테이블 파티션 속성을 그대로 상속받는다. 따라서 테이블 파티션 키가 주문일자라면 인덱스 파티션 키도 주문일자가 된다. 로컬 파티션 인덱스는 테이블과 정확히 1:1 대응 관계를 갖도록 오라클이 파티션을 자동으로 관리해준다. 테이블 파티션 구성을 변경하더라도 인덱스를 재생성할 필요가 없다. 변경 작업이 순식간에 끝나므로 피크 시간대만 피하면 서비스를 중단하지 않고도 작업할 수 있다. 즉 관리 편의성이 있다.

 

글로벌 파티션 인덱스

파티션을 테이블과 다르게 구성한 인덱스다. 파티션 유형이 다르거나, 파티션 키가 다르거나, 파티션 기준값 정의가 다른경우이다. 비파티션 테이블이어도 인덱스는 파티셔닝 할 수 있다.

 

테이블 파티션 구성을 변경 (drop, exchange, split)하는 순간 Unusable 상태로 바뀌므로 곧바로 인덱스를 재생성해줘야한다. 그동안 해당 테이블을 사용하는 서비스를 중단해야한다.

테이블과 인덱스가 정확히 1:1관계가 되도록 DBA가 파티션을 직접 구성할 수 있지만 그것은 로컬 파티션이 아니다. 모양만 로컬

 

비파티션 인덱스

말그대로 파티셔닝하지 않은 인덱스이낟.

일반 CREATE문이다.

테이블 파티션 구성을 변경하는 순산 Unusable 상태로 바뀌므로 곧바로 인덱스를 재생성해줘야한다. 그동안 해당 테이블을 사용하는 서비스를 중단해야 한다.

 

Prefixed vs Nonprefixed

  • Prefixed : 인덱스 파티션 키 컬럼이 인덱스 키 컬럼 왼쪽 선두에 위치한다.
  • Nonprefixed : 인덱스 파티션 키 컬럼이 인덱스 키 컬럼 왼쪽 선두에 위치하지 않는다. 파티션 키가 인덱스 컬럼에 아예 속하지 않을 때도 여기에 속한다.

 

중요한 인덱스 파티션 제약

Unique 인덱스를 파티셔닝하려면 파티션 키가 모두 인덱스 구성 컬럼이어야한다.

주문일자로 파티셔닝한 테이블이 있을때 PK = 주문일자 + 주문번호, 인덱스는 로컬 파티션이다. PK 인덱스도 주문일자로 파티셔닝한 셈이므로 파티션 키가 인덱스 구성 컬럼이다.

이때 주문 레코드를 입력하면 중복 값 확인을 위해 한 파티션 인덱스만 탐색하면 된다.

 

PK = 주문 번호, 단일컬럼인 경우, 테이블 파티션 키인 주문일자가 인덱스 구성 컬럼이 아니다. 파티셔닝을 허용했다고 가정하면 중복값이 있는지 확인하려고 인덱스 파티션을 모두 탐색해야한다.

 

이렇게 Unique 인덱스를 파티셔닝할때 파티션 키가 인덱스 컬럼에 포함돼야한다는 조건은 DML 성능 보장을 위해 단연히 있어야 할 제약조건이다. 그리고 파티션 키 조건 없이 PK 인덱스로 액세스하는 수많은 쿼리 성능을 위해서도 필요하다.

 

문제는, 이 제약으로 인해 PK 인덱스를 로컬 파티션하지 못하면 파티션 Drop, Truncate, Exchange, Split, Merge 같은 파티션 구조 변경 작업도 쉽지 않다는 데 있다. 이들 작업을 하는 순간, PK 인덱스가 Unusable 상태로 바뀌기 때문이다. 곧바로 인덱스를 Rebuild 하면 되지만, 그동안 해당 테이블을 사용하는 서비스를 중단해야 한다. 서비스 중단 없이 파티션 구조를 빠르게 변경하려면, PK를 포함한 모든 인덱스가 로컬 파티션 인덱스이어야 한다.

OLTP는 기준성 데이터, 특정 고객, 특정 상품, 최근 거래 등을 반복적으로 읽기때문에 버퍼캐시 성능 향상에 도움을 준다.

하지만 DW/OLAP나 배치 프로그램에서 사용하는 SQL은 주로 대량 데이터를 처리하기 때문에 버퍼캐시를 경유하는 I/O 매커니즘이 오히려 성능을 떨어뜨린다. 그래서 버퍼캐시를 경유하지 않고 곧바로 데이터 블록을 읽고 쓸수있는 Direct Path I/O 기능을 제공한다.

 

Direct Path I/O

블록 I/O는 DB버퍼 캐시를 경유한다. 읽고자하는 블록을 먼저 버퍼캐시에서 찾아보고, 찾지 못할 때만 디스크에서 읽는다. 데이터를 변경할 때도 먼저 블록을 버퍼캐시에서 찾는다. 찾은 버퍼블록에 변경을 가하고 나면, DBWR 프로세스가 변경된 블록들을 주기적으로 찾아 데이터파일에 반영한다.

 하지만 대량 데이터를 읽고 쓸 때 건건이 버퍼캐시를 탐색한다면 개별 프로그램 성능에는 오히려 안좋다. 버퍼캐시에서 블록을 찾을 가능성이 거의 없기 때문이다. 대량 블록을 건건이 디스크로부터 버퍼캐시에 적재하고서 읽어야 하는 부담도 크다. 또한 Full Scan 위주로 가끔 수행되는 대용량 처리 프로그램이 읽어 들인 데이터는 대게 재사용성이 낮다.

  1. 병렬 쿼리로 Full Scan을 수행할 때
  2. 병렬 DML을 수행할 때
  3. Direct Path Insert를 수행할 때
  4. Temp 세그먼트 블록들을 읽고 쓸 때
  5. direct 옵션을 지정하고 export를 수행할 때
  6. nocache 옵션을 지정한 LOB 컬럼을 읽을 때

Direct Path I/O 기능이 작동한다.

 

 

Direct Path Insert

  1. 데이터를 입력할 수 있는 블록을 Freelist에서 찾는다. 테이블 HWM 아래쪽에 있는 블록 중 데이터 입력이 가능한 블록을 목록으로 관리하는데, 이를 Freelist라고 한다.
  2. Fresslist에서 할당받은 블록을 버퍼캐시에서 찾는다.
  3. 버퍼캐시에 없으면, 데이터파일에서 읽어 버퍼캐시에 적재한다.
  4. INSERT 내용을 Undo 세그먼트에 기록한다.
  5. INSERT 내용을 Redo 로그에 기록한다.

-> INSERT가 느린이유

 

Direct Path Insert 방식을 사용하면 대량 데이터를 일반적인 INSERT 보다 훨씬 빠르게 입력할 수 있다.

  • INSERT --- SELECT 문에 append 힌트 사용
  • parallel 힌트를 이용해 병렬 모드로 INSERT
  • direct 옵션을 지정하고 SQL*Loader(sqlldr)로 데이터 적재
  • CTAR (create table ---as select) 문 수행

Direct Path Insert 방식이 빠른이유

  1. Freelist를 참조하지 않고 HWM 바깥 영역에 데이터를 순차적으로 입력한다.
  2. 블록을 버퍼캐시에서 탐색하지 않는다.
  3. 버퍼캐시에서 적재하지 않고, 데이터파일에 직접 기록한다
  4. Undo 로깅을 안한다
  5. Redo 로깅을 안하게 할 수 있다. 테이블을 아래와 같이 nologging 모드로 전환한 상태에서 Direct Patch Insert 안하면됨 -> alter table t NOLGGING

Array Processing도 Direct Path Insert 방식으로 처리할 수 있다. append_values 힌트를 사용하면된다.

 

Direct Path Insert 주의점

2번

  • 성능은 빨라지지만 Exclusive 모드 TM Lock이 걸린다. -> 커밋하기 전까지는 다른 트랜잭션은 해당 테이블에 DML을 수행하지 못한다. 트랜잭션이 비번한 주간에 이 옵션을 사용하는 것은 금물
  • Freelist를 주회하지않고 HWM 바깥 영역에 입력하므로 테이블에 여유 공간이 있어도 재활용하지 않는다는 사실, 과거 데이터를 주기적으로 DELECT 해서 여유 공간이 생겨서 이 방식으로만 계속 INSERT 하는 테이블은 사이즈가 줄지않고 계속 늘어난다. Range 파티션 테이블이면 과거 데이터를 DELECT가 아닌 파티션 DROP 방식으로 지워야한다. 비파티션 테이블이면 주기적으로 Reorg 작업을 수행해야한다.

병병렬 DML

Insert는 append 힌트를 이용해 Direct Path Write 방식으로 유도할 수 있지만, UPDATE, DELETE는 기본적으로 Direct Path Write가 불가능하다. 유일한 방법은 병렬 DML로 처리하는것, 병렬처리는 대용량 데이터가 전제이므로 오라클은 병렬 DML에 항상 Direct Path Write 방식을 사용한다.

먼저 

alther session enable parallet dml;

로 병렬 DML 활성화한다.

이렇게 힌트를 사용하면 병렬로 진행한다.

 

만약 병렬DML을 활성화하지 않고 쓰면 병목현상이 발생한다.

 

병렬 INSERT는 append 힌트를 지정하지 않아도 Direct PAth Inser방식을 사용한다. 병렬 DML이 작동하지 않을 경우 append 힌트를 같이 사용하는 것이 좋다. 병렬 DML이 작동하지 않더라도 QC가 Direct PAth Insert를 사용하면 어느정도 만족할만한 성능을 낼수있다.

 

트랜잭션이 빈번한 주간에 이 옵션을 사용하지 말자. Exclusive 모드 TM Lock이 걸린다.

 

 

수정가능 조인 뷰

update 고객 c
set 최종거래일시 = (select max(거래일시) from 거래
where 고객번호 = c.고객번호
and 거래일시 >= trunc(add_months(sysdate, -1)))
, 최근거래횟수 = (select count(*) from 거래
where 고객번호 = c.고객번호)
, 최근거래금액 = (select sum(거래금액) from 거래
where 고객번호 = c.고객번호
and 거래일시 >= trunc(add_months(sysdate, -1)))
where exists (select 'x' from 거래
where 고객번호 = c.고객번호
and 거래일시 >= trunc(add_months(sysdate, -1)))

위 sQL을 이렇게 고칠수있다.

한달 이내 고객별 거래 데이터를 두번 조회하기 때문에 비효율이 존재한다. 총 고객 수와 한달 이내 거래 고객 수에 따라 성능이 좌우된다.

총 고객 수가 아주 많다면 Exists 서브쿼리를 써서 세미 조인을 유도한다.

 

/


만약 한달 이내 거래를 발생시킨 고객이 많아 UPDATE 발생량이 많다면 이렇게 변경을 고려할 수 있다. 하지만 모든 고객 레코드에 LOCK이 걸리고 같은 값으로 갱신되는 비중이 높을수록 Redo 로그 발생량이 증가해 오히려 비효율적일수있다.

 

12c이상에서만 정상 실행, 10이하는 UPDATE 옆에 bypass_ujvc 힌트를 써야한다.

이렇게 수정가능 조인 뷰를 활용하면 참조 테이블과 두번 조인하는 비효율을 없일수있다.

'조인 뷰'는 FROM 절에 두 개 이상 테이블을 가진 뷰를 가리키며 '수정가능 조인 뷰'는 말그대로 입력, 수정, 삭제가 허용되는 조인 뷰를 말한다. 단 1쪽 집합과 조인하는 M쪽 집합에만 입력, 수정, 삭제가 허용된다.

 

job이 CLERK인 레코드의 loc를 모두 SEOUL로 변경하는 것을 허락하면 어떤일이 발생할까?

job이 CLERK인 사원이 10,20,30부서에 모두 속해있는데 그러면 세 부서 loc이 모두 SEOUL로 바뀔 것이다. 다른 job을 가진 부서 소재지까지 바뀌는 것은 원하는 결과가 아니다.

1쪽 집합과 조인하는 M쪽 집합의 컬럼을 수정하면

이런 에러가 발생한다. 옵티마이저가 지금 어느 테이블이 1쪽 집합인지 알수없어 생기는 에러다. DELETE INSERT도 마찬가지다.

이렇게 1쪽 집합에 PK제약을 설정하거나 Unique 인덱스를 생성해야 수정가능 조인뷰를 통한 입력/수정/삭제가 가능한다.

 

PK 제약을 설정하면 EMP 테이블은 키-보존 테이블, DEP테이블은 비 키-보존 테이블로 남는다.

 

 

 

수정 가능한 조인 뷰(Updatable/Modifiable Join View)

기본 개념

조인 뷰란 두 개 이상의 테이블을 조인해서 만든 가상 테이블. 일반적으로 뷰는 조회만 가능하지만, 특정 조건을 만족하면 수정도 가능. 오라클 12c 이상 버전에서 정상적으로 작동.

예시에서 사용된 테이블 구조

- EMP: 직원 정보 테이블 (직원번호, 이름, 직무, 급여 등)
- DEPT: 부서 정보 테이블 (부서번호, 부서명, 위치 등)
- EMP_DEPT_VIEW: 두 테이블을 조인한 뷰

실습 과정과 결과

# 뷰 생성
CREATE
VIEW EMP_DEPT_VIEW
AS SELECT e.*, d.dname, d.loc FROM emp e, dept d
WHERE e.deptno = d.deptno;
# CLERK 직무를 가진 직원들의 위치를 SEOUL로 변경 시도
UPDATE EMP_DEPT_VIEW SET loc = 'SEOUL' WHERE job = 'CLERK';

주요 규칙과 제한사항

1:M 관계에서는 M쪽 테이블만 수정 가능 수정하려는 컬럼이 어느 테이블의 것인지 명확해야 함 Key-Preserved Table만 수정 가능 Key-Preserved Table: 조인 후에도 키 값의 유일성이 보장되는 테이블

발생할 수 있는 오류들

잘못된 수정 시도 시 발생하는 오류 ORA-01779: cannot modify a column which maps to a non key-preserved table
뷰에서 삭제 시도 시 발생하는 오류 ORA-01752: cannot delete from view without exactly one key-preserved table

해결 방법

1:1 관계의 테이블만 사용 PK 제약조건이나 Unique 인덱스 설정 Key-Preserved Table만 수정하도록 제한

실무 활용 팁

복잡한 조인 뷰보다는 단순한 구조 사용 권장 수정이 필요한 경우 원본 테이블 직접 수정 고려 반드시 테스트 환경에서 먼저 검증
이렇게 수정 가능한 조인 뷰는 편리하지만, 여러 제약사항이 있으므로 신중하게 사용

 

키 보존 테이블

키 보존 테이블 : 조인된 결과집합을 통해서도 중복 값 없이 Unique하게 식별이 가능한 테이블. Unique한 1쪽 집합과 조인되는 테이블이어야 조인된 결과집합을 통한 식별이 가능한다.

dept_rid에 중복 값이 나타나고있다. emp_rid는 중복값이 없으며 뷰의rowid와 일치한다. 즉 뷰에 rowid를 제공하는 테이블이 키 보존 테이블이다.

DEPT 테이블로부터 Unique 인덱스를 제거하면 키 보존 테이블이 없기때문에 뷰에서 rowid를 출력할 수 없게 된다.

 

ORA-01779 오류 회피

부서별 평균 급여를 계산해서 방금 추가한 컬럼에 반영

11g이하 버전에서 UPDATE문을 실행하면 ORA-01779 에러가 발생한다. EMP 테이블을 DEPTNO로 Group by했으므로 DEPTNO 컬럼으로 조인한 DEPT 테이블은 키가 보존되는데도 옵티마이저가 불필요한 제약을 가한 것

 

MERGE 문 활용

DW에서 가장 흔히 발생하는 오퍼레이션은 기간계 시스템에서 가져온 신규 트랜잭션 데이터를 반영함으로써 두 시스템 간 데이터를 동기화 하는 작업이다.

 

고객 테이블에서 발생한 변경분 데이터를 DW에 반영하는 프로세스

이 중 3번 적재 작업을 효과적으로 지원하기 위해 오라클9i에서 MERGE문이 도입됐다.

 

Source 테이블 기준으로 Target 테이블과 Left Outer 방식으로 조인해서 조인에 성공하면 UPDATE, 실패 INSERT 한다. MERGE 문을 UPSERT라고 부르는 이유다. 위 MERGE 문에서 Source는 Customer_Delta테이블이고 Target은 Customer 테이블이다.

 

Optional Clauses

 

Conditional Operations

 

DELETE Clause

 

 

데이터베이스 Call과 성능

 

SQL은 아래 세 단계로 나누어 실행된다.

  • Parse Call : SQL 파싱과 최적화를 수행하는 단계, SQL과 실행계획을 라이브러리 캐시에서 찾으면, 최적화 단계는 생략할 수 있다.
  • Execute Call : SQL을 실행하는 단계, DML은 이 단계에서 모든 과정이 끝나지만 SELECT 문은 Fetch 단계를 거친다.
  • Fetch Call : 데이터를 읽어서 사용자에게 결과집합을 전송하는 과정으로, SELECT 문에서만 나타난다. 전송할 데이터가 많을 때는 Fetch Call이 여러 번 발생한다.

Call이 어디서 발생하느냐에 따라 User Call과 Recursive Call로 나눈다,

  • User Call : 네트워크를 경유해 DBMA 외부로부터 인입되는 Call, User는 클라이언트 단에 위치한다. 하지만 DBMS 입장에서는 사용자는 WAS(AP서버)다. 3-Tier 아키텍처에서 "User Call은 WAS에서 발생하는 Call이다.
  • Recurive Call : DBMS 내부에서 발생하는 Call이다. SQL 파싱과 최적화 과정에서 발생하는 데이터 딕셔너리 조회, PL/SQL로 작성한 사용자 정의 함수/프로시저/트리거에 내장된 SQL을 실행할 때 발생하는 Call이다.

어떤 Call이든 위에 Parse, Execute, Fetch Call단계를 거친다. 데이터베이스 Call이 많으면 성능이 느릴 수 밖에없다. 네트워크를 경유하는 User Call이 성능에 미치는 영향은 매우크다.

 

절차적 루프 처리

SOURCE 테이블에 레코드 100만개가 입력되어있다.

PL/SQL 프로그램에서 SOURCE 테이블을 읽어 100만번 루프를 돌면서 TARGET 테이블에 입력할때 루프를 돌면서 Call이 발생했지만. 네트워크를 경유하지 않는 Recursive Call이므로 29초가 걸렸다.

JAVA는 네트워크를 경유하는 User Call이므로 성능이 218초로 급격히 나빠졌다.

 

One SQL의 중요성

단 한번의 Call로 처리하니 1초가 걸렸다. 그러니 가급적 One SQL (데이터베이스에서 여러 데이터에 대한 처리를 하나의 SQL문으로 처리하는 것) 로 구현하려고 노력해야한다.

아래 구문 활용법을 잘 익혀야한다.

  • Insert Into Select
  • 수정가능 조인 뷰
  • Merge 문

Array Processing 활용

절차적 프로그램을 One Sql로 구현하는 일은 쉽지않다. 복잡한 업무 로직을 포함하는 경우가 많기 때문이다. Array Processing 기능을 활용하면 One SQL로 구현하지 않고도 Call 부하를 획기적으로 줄일수있다.

11초 걸림

만번에 한번씩 Insert 하도록 구현해서 백만번할 Call을 백번으로 줄였기 때문이다. Call을 단 하나로 줄이지 못해도 Array Processing을 활용해 10~100번 수준으로 줄일 수 있으면 성능효과가 좋다.

 

인덱스 및 제약 해제를 통한 대량 DML 튜닝

OLTP에서 인덱스와 무결성 제약 조건을 해제할 순없다. 하지만 동시 트랜잭션없이 대량 데이터를 적재하는 Batch 에서는 이런 기능을 해제해서 큰 성능개선 효과를 얻을 수 있다.

PK 제약으로 Unique 인덱스 생성, 일반 인덱스 생성 총 2개

PK제약과 인덱스가 있는 상태에서 1분 19초 걸렸다.

 

PK와 인덱스를 해제하니 약 6초가 걸렸다.

PK 제약을 활성화하고 일반 인덱스를 재생성하니 8초걸렸다.

 

 

  1. 첫 번째 테스트 (PK 제약과 Unique 인덱스 사용)
  • SOURCE 테이블에 1,000만 건의 데이터 생성
  • TARGET 테이블에 PK 제약조건과 인덱스 생성
  • 1,000만 건 입력 시 약 1분 19초 소요
  1. 두 번째 테스트 (PK 제약과 인덱스 해제)
  • PK 제약 비활성화하고 인덱스를 Unusable 상태로 변경
  • skip_unusable_indexes = true 설정
  • 동일한 1,000만 건 입력 시 약 5.84초로 대폭 단축
  • NOVALIDATE 옵션 사용으로 시간 추가 단축
  1. 세 번째 테스트 (Non-Unique 인덱스 사용)
  • PK 제약에 Non-Unique 인덱스를 사용
  • 제약조건은 비활성화하되 인덱스는 유지
  • 역시 빠른 성능을 보여줌

결론: 대량 데이터 입력 시 제약조건과 인덱스를 적절히 제어함으로써 성능을 크게 향상시킬 수 있음을 보여줌. 특히 제약조건 비활성화와 NOVALIDATE 옵션 사용이 효과적.

 

주요 성능 개선 포인트:

  1. 제약조건 비활성화로 인한 검증 과정 생략
  2. Unusable 인덱스 설정으로 인덱스 관리 부하 감소
  3. NOVALIDATE 옵션으로 데이터 검증 과정 최소화
  4. Non-Unique 인덱스 활용으로 유연한 구조 확보

실무 적용 시 고려사항:

  • 데이터 무결성과 성능 사이의 균형 필요
  • 대량 데이터 처리 시 임시적으로 제약조건을 해제하고 작업 후 다시 활성화하는 전략 유용
  • NOVALIDATE 옵션 사용 시 데이터 정합성에 대한 별도 검증 필요할 수 있음
  • 작업 완료 후 인덱스와 제약조건의 적절한 재활성화 필요

DML 성능에 영향을 미치는 요소

  • 인덱스
  • 무결성 제약
  • 조건절
  • 서브쿼리
  • Redo 로깅
  • Undo 로깅
  • Lock
  • 커밋

인덱스

테이블에 레코드를 입력하면, 인덱스에도 인력해야한다. 테이블은 Freelist를 통해 입력할 블록을 할당받지만, 인덱스는 정렬된 자료구조이므로 수직적 탐색을 통해 블록을 찾아야한다. (Freelist : 테이블마다 데이터 입력이 가능한 블록 목록을 관리하는 것)

이는 DELETE 할때도 마찬가지로, 레코드를 하나 삭제하면 인덱스 레코드를 모두 찾아서 삭제해야한다.

UPDATE할 때는 변경된 컬럼을 참조하는 인덱스만 찾아서 변경해주면 된다. -> 테이블은 한 건 변경할 때마다 인덱스에는 두 개 오퍼레이션이 발생한다. (ex. A->K로 변경하면 저장 위치도 달라지므로 삭제후 삽입하는 방식으로 처리한다.)

 

이렇게 DELETE, UPDATE할때 인덱스를 찾으므로 인덱스 개수는 DML 성능에 미치는 영향이 크다. 인덱스 늘때마다 TPS 증가

예시

create table source
as
select b.no, a.*
from (select * from emp where rownum <= 10) a
,(select rownum as no from dual connect by level <= 100000) b;

create table target
as
select * from source where 1 = 2;

alter table target add
constraint target_pk primary key(no, empno);

SOURCE 테이블에 레코드가 100만개 입력되어있고 TARGET 테이블은 비어있다.

TARGET 테이블에 PK 인덱스 하나만 생성하여 SOURCE 테이블을 읽어 레코드 100만개를 입력해보다.

그러니까 약 5분이 걸렸다.

인덱스 두개를 더 생성하고 100만건 생성하니 39초로 매우 느려졌다.

 

무결성 제약과 DML 성능

  • 개체 무결성 : 테이블의 기본키(Primary Key)는 NULL 값을 가질 수 없으며 중복된 값을 허용하지 않음.
  • 참조 무결성 : 외래키(Foreign Key)가 참조하는 테이블의 기본키와 일치하거나 NULL이어야 함
  • 도메인 무결성 : 각 속성(컬럼)의 값은 해당 도메인에서 정의된 값만을 가질 수 있음
  • 사용자 정의 무결성 (업무 제약 조건) : 업무 규칙이나 도메인 특성에 따라 사용자가 직접 정의하는 제약조건

DBMS에서 PK, FK, Check, Not Null 같은 제약을 설정하면 더 완벽하게 데이터 무결성을 지켜낼 수 있다.

PK, FK 제약은 Check, Not Null 제약보다 성능에 더 큰 영향을 미친다.

Check, Not Null은 정의한 제약 조건을 준수하는지만 확인하지만, PK, FK제약은 실제 데이터를 조회해봐야하기때문

이런 결과가 나온다.

 

조건절과 DML 성능

SELECT와 실행계획이 다르지 않다. 그래서 튜닝 원리를 그대로 적용할 수 있다.

 

서브쿼리와 DML 성능

SELECT 문과 실행계획이 다르지 않다.

 

Redo 로깅과 DML 성능

오라클은 데이터파일과 컨트롤 파일에 가해지는 모든 변경사항을 Redo 로그에 기록한다.

Redo 로그는 트랜잭션 데이터가 어떤 이유에서건 유실되었을때 트랜잭션을 재현하여 유실 이전 상태로 복수한다.

DML을 수행할 때마다 Redo 로그를 생성해야 하므로 Redo 로깅은 DML 성능에 영향을 미친다.

INSERT 작업에 대해 Redo 로깅 생략 기능을 제공하는 이유이다.

 

Redo 로그 용도

  • Database Recovery : 온라인 Redo 로그를 백업해둔 Archived Redo 로그를 이용하여 데이터베이스 복구
  • Cache Recovery (Instance Recovery 시 roll forward 단계) : 버퍼캐시는 휘발성이라 캐시에 저장된 변경사항이 비정상적으로 종료되면 작업내용을 잃는다. 이런 유실을 막기위함
  • Fast Commit : 디스크 상 데이터 블록은 랜덤 액세스 방식으로 반영되서 느리다. 로그는 Append 방식으로 기록해서 빠르다. 그래서 ㅊ트랙잭션에 의한 변경사항을 우선 Append 방식으로 빠르게 로그 파일에 기록하고, 변경된 메모리 버퍼블록과 데이터파일 블록 간 동기화는 적절하게 (DBWR, Checkpoint)을 이용해 배치로 수행한다. 즉 버퍼블록에만 기록되고 디스크에 기록되지않았지만 Redo 로그를 믿고 빠르게 커밋을 완료했다는 의미

Undo 로깅과 DML 성능

 

트랙잭션을 롤백해서 현재상태를 과거 상태로 돌리는것

Redo는 트랜잭션을 재현하는 데 필요한 정보를 로깅하고, Undo에는 변경된 블록을 이전 상태로 되돌리는 데 필요한 정보를 로깅한다.

Undo 로깅도 DML 성능에 영향을 미친다.

  • Transaction Rollback : 트랜잭션에 의한 변경사항을 최종 커밋하지 않고 롤뱃
  • Transaction Recovery : 시스템이 셧다운된 시점에 아직 커밋되지 않은 트랙잭션 롤백
  • Read Consistency : 읽기 일관성.

 

MVCC 모델

MVCC(Multi-Version Concurrency Control)는 데이터베이스의 동시성 제어를 위한 매커니즘

기본 개념:

  • 데이터를 업데이트할 때 기존 데이터를 바로 변경하지 않고 새로운 버전의 데이터를 생성
  • 각 트랜잭션은 데이터의 특정 시점 스냅샷을 봄
  • 읽기 작업이 쓰기 작업을 차단하지 않음
  • Current 모드 : 디스크에서 캐시로 적재된 원본 블록을 현재 상태 그대로 읽는 방식
  • Consistent 모드 : 쿼리가 시작된 이후 다른 트랜잭션에 의해 변경된 블록을 만나면 원본 블록으로부터 복사본 블록을 만들고 거기에 Undo 데이터를 적용하므로써 쿼리가 '시작된 시점'으로 되돌려서 읽는 방식 (즉 원본 블록하나에 여러 복사본이 존재할수있음)
    • SCN : 시스템에서 마지막 커밋이 발생한 시점정보를 SCN이라는 글로벌 변수값으로 관리. 트랜잭션 커밋할 때마다 1씩증가하고 오라클 백그라운드 프로세서에 의해서도 조금씩 증가.

Lock과 DML 성능

Lock은 DML 성능에 매우 크고 직접적인 영향을 미친다. Lock을 필요 이상으로 자주, 길게 사용하거나 레벨을 높일수록 DML 성능은 느려진다. 그러나 적게 짧게 낮게 쓰면 데이터 품질이 나빠진다. 그래서 두 마리 토끼 잡으려면 동시성 제어가 필요하다.

동시성 제어는 동시에 실행되는 트랜잭션 수를 최대화하면서 데이터 무결성을 유지하기위해 노오력하는것

 

커밋과 DML 성능

커밋은 DML과 별개로 실행하지만, DML을 끝내려면 커밋까지 완료해야하므로 서로 밀접한 관계가 있다.

DML이 Lock에 의해 블로킹되는 경우, 커밋은 DML 성능과 직결된다. 

DML이 Lock을 푸는 열쇠가 커밋이다. 커밋은 가벼운 작업이 아니다.

 아래는 커밋의 내부 메커니즘이다.

  1. DB 버퍼캐시 : 서버 프로세스는 버퍼캐시를 통해 데이터를 읽고 쓴다. 버퍼캐시에서 변경된 블록을 모아 주기적으로 데이터파일에 일괄기록하는 작업은 DBWR 프로세스가 맡는다. 배치 방식으로 처리한다.
  2. Redo 로그 버퍼 : 버퍼캐시는 휘발성이므로 DBWR 프로세스가 Dirty 블록들을 데이터파일에 반영할 때까지 불안한 상태라고 생각할 수 있지만 버퍼캐시에 가한 변경사항을 Redo 로그에도 기록하므로 안정하다. 데이터가 유실되도 Redo로그를 이용해 복구가능.그런데 Redo 로그도 파일이다. Append 방식으로 기록하더라도 디스크 I/O는 느리다. Redo 로깅 성능 문제를 해결하기 위해 오라클은 로그버퍼를 이용한다. Redo 로그 파일에 기록하기 전에 먼저 로그버퍼에 기록하는 방식이다. 로그버퍼에 기록한 내용은 나중에 LGWR 프로세스가 Redo 로그 파일에 배치로 일괄 기록한다.
  3. 트랙잭션 데이터 저장과정
    1. DML문을 실행하면 Redo 로그버퍼에 변경사항을 기록한다.
    2. 버퍼블록에서 데이터를 변경(추가/수정/삭제)한다. 버퍼캐시에서 블록을 찾지 못하면 데이터파일에서 읽는 작업
    3. 커밋
    4. LGWR 프로세스가 Redo 로그버퍼 내용을 로그파일에 일괄 저장
    5. DBWR 프로세스가 변경된 버퍼블록들은 데이터파일에 일괄 저장

  데이터를 변경하기전에 항상로그부터 기록한다. 서브 프로세스가 버퍼블록에서 데이터를 변경(2)하기 전에 Redo 로그버퍼에 로그를 먼저 기록(1)하는 이유다. DBWR 프로세스가 Dirty 블록을 디스크에 기록(5)하기 전에 LGWR 프로세스가 Redo 로그파일에 로그를 먼저 기록하는(4) 이유다. -> Write Ahead Logging

 DBWR, LGWR 프로세스는 주기적으로 깨어나 각각 Diry 블록과 Redo 로그버퍼를 파일에 기록한다. LGWR 프로세스는 서버 프로세스가 커밋을 발행했다고 신호를 보낼때도 깨어나서 활동시작한다. -> Log Force at Commit,

이렇게 Redo 로그가 휘발성 로그버퍼에 기록해도 트랜잭션 데이터를 지킬수있다.

 

      4. 커밋 = 저장버튼

         커밋은 문서 작업 도중 저장 버튼을 누르는 것과 같다. 서버 프로세스가 그때까지 했던 작업을 디스크에 기록하라는 명령어이다. 그래서 저장을 완료할때까지 서버프로세스는 다음 작업을 진행할 수 없다. 작업이 완료했다는 신호를 받아야 진행한다. Sync 방식

LGWR 프로세스가 Redo 로그에 기록하는 작업은 디스크 I/O작업이다. 그래서 커밋은 느리다.

트랜잭션을 논리적으로 잘 정의함으로써 불필요한 커밋이 발생하지 않도록 구현해야한다.

 

양이 너무 많은거시에요

  • Kafka Streams
    • 실시간 데이터 처리를 위한 클라이언트 라이브러리
    • 분산 환경에서 고성능 유지
    • 상태 저장 및 비저장 처리 지원
    • 정확히 한 번 처리 보장
    • Stateful processing : 윈도우 연산, 조인 연산, 집계 가능
    • KTable, KStream
      • KTable : 단순한 데이터 스트림 흐름
      • KStream : 상태 기반의 데이터 구조, 최신 상태만 유지하며 업데이터가 일어날 때마다 데이터가 덮어 쓰여짐
  • Kafka Connect
    • 데이터 통합을 위한 분산 프레임워크
    • 데이터 데이터 소스/싱크 연결
    • 확장 가능한 플러그인 아키텍쳐
    • 내장 및 커스텀 커넥터 지원
    • 활용 사례
      • 데이터베이스CDC (Change Data Capture)
      • 로그 파일 스트리밍
      • 클라우드 스토리지 연동
  • Broker 설정 및 튜닝
    • 리텐션 정책 설정
      • 리텐션 기간 설정 
      • 세그먼트 크기 최적화
      • 고려사항 : 스토리지 용량 vs 데이터 보존 기간
    • 리더와 팔로워 관리
      • Replication Factor 설정
      • ISR(In-Sync Replicas) 관리
      • 리더 선출 전략
  • Producer 설정
    • Idempotent Producer
      • 중복 메시지 방지
    • Transactional Producer : 원자적 메시지 전송
    • 압축 설정
  • Consumer 리밸런싱 전략
    • 컨슈머 그룹 관리 : 파티션 재배치 최적화
    • 리밸런싱 정략 : 
      • Sticky Assignor
      • Cooperative Sticky Assignor
      • 커스텀 파티션 할당 전략
      • 정적 멤버십
      • 증분식 리밸런싱
  • Consumer Offset 관리
    • 자동 offset 커밋
      • 주기적 자동 커밋
      • 장점 : 간단한 구현과 관리
      • 단점 : 중복 처리 가능성
    • 수동 Offset 관리
      • 관리자가 직접 커밋
      • 장점 : 정확한 처리 보장
      • 단점 : 복잡한 구현
  • Replication Factor 및 파티셔닝 전략
    • Replication Factor 조정 : 데이터 내구성과 장애 복구 능력 향상
    • 커스터 파티셔닝 전략 : 데이터 로컬리티 향상
  • SSL/TLS 구성
    • SSL 구성 : 데이터 암호화 및 보안 통신
    • SASL을 통한 인증 : 다양한 인증 매커니즘 지원, Kerberos, SCRAM
  • ACL 보안 관리
    • 세밀한 접근 제어 : 특정 사용자나 애플리케이션이 특정 토픽에 접근할 수 있도록 설정
    • 보안 정책 적용 및 모니터링 : 보안 로그를 통해 모든 보안 이벤트를 기록, 이상행동 탐지, 칩입 방지
     

'Backend' 카테고리의 다른 글

카프카  (5) 2025.02.13
Redis 개념  (0) 2025.02.09
시스템 확장  (0) 2025.02.08
분산 시스템  (0) 2025.02.03
대규모 트래픽 처리  (0) 2025.02.03

  • 카프카 : 메시징 시스템 개념
    • 분산 메시징 시스템
    • 실시간 데이터 스트리밍
    • 로그 처리
  • 핵심 특징
    • 확장성 : 분산 시스템 설계, 수평 확장 용이
    • 내구성 : Replication 기능
    • 높은 처리량 : 배치 처리와 압축 통한 성능 최적화
  • 아키텍쳐 : Producer, Consumer
    • Producer
      • 데이터 생성 및 카프카 클러스터로 전송
      • 메시지 전송 과정
        • 특정 토픽의 파티션으로 데이터 전송
        • 파티션 선택 전략: 라운드 로빈, 키 기반 해시
      • Ack 설정
        • acks = all: 높은 내구성 보장
    • Consumer
      • 카프카에서 데이터 읽기
      • Consumer Group
        • 병렬 처리 가능
        • 하나의 파티션은 하나의 컨슈머에만 할당
      • 데이터 중복 및 누락 방지
        • offset 관리
    • Producer-Consumer 흐름
      • 데이터 흐름
        • 프로듀서 -> 토픽 (파티션) -> 컨슈머
        • 높은 처리량과 확장성
    • 브로커
      • 카프카 클러스터의 서버 노드
      • 브로커 클러스터
        • 여러 브로커로 구성
        • 데이터 저장 및 관리
      • 리더와 팔로워 구조
        • 리더 : 주 데이터 처리
        • 팔로워 : 데이터 복제 및 장애 복구 준비
    • 토픽
      • 메시지 카테고리
      • 토픽의 구조
        • 여러 파티션으로 구성
        • 병렬 처리 가능
      • 데이터 처리 전략 : 발행/구독 모델
    • 브로커 - 토픽 관계
      • 데이터 분산 저장
        • 토픽의 파티션이 여러 브로커에 분산
        • 고가용성과 성능 보장
    • 파티션
      • 카프카의 핵심 처리 단위
      • 토픽을 구성하는 단위
      • 특징
        • 고유 번호 부여
        • 물리적으로 다른 브로커에 분산 저장
      • 병렬 처리 : 고성능 데이터 처리 가능
      • 데이터 저장 구조 : 로그 파일 형식
    • Replication
      • 데이터 복제를 통한 내구성과 고가용성 보장
      • 리더-팔로워 구조
        • 리더 : 주 데이터 처리
        • 팔로워 : 데이터 복제 및 백업
      • Replication Factor
        • 일반적으로 2~3개의 복제본 유지
        • 장애 내성 vs 리소스 사용량 trade-off
    • 파티션-Replication
      • 내구성 보장 : 데이터 손실 방지, 고가용
    • Offest
      • 컨슈머의 메시지 읽기 위치 기억
      • 메시지 일관성 유지
        • 중복 처리 방지
        • 처리 일관성 유지
      • 관리 방식
        • 자동 커밋 : 카프카가 자동으로 offset 저장
        • 수동 커밋 : 컨슈머가 명시적으로 Offset 저장, 안정한 메시지 처리 보장
      • offset과 메시지 처리 일관성
        • 정확히 한번 처리 가능
        • 데이터의 일관성 유지
        • 중복 메시지 처리 방지

///////

  • 카프카의 역할
    • 중앙 집줍형 로그 관리 시스템 구축
    • 대규모 시스템에서 로그 데이터 효율적 처리
    • 장애 및 성능 문제 신속 파악
  • 활용 사례
    • 웹 애플리케이션: 오류 로그, 성능 메트릭 수집
    • 장애 탐지 및 대응 시간 단축
    • 데브옵스 환경 : 인프라 상태 모니터링 및 자동화 대응
  • 대규모 데이터 스트리밍 시스템
    • 여러 데이터 소스에서 실시간 데이터 수집
    • 스트리밍 분석 시스템으로 데이터 전송
  • 적용 사례
    • IOT 장치
    • 실시간 데이터 파이프라인 구축
    • 비즈니스 인텔리전스 : 실시간 보고서 생성 및 분석
  • 사용 사례
    • 중앙 로그 관리
      • 여러 서버의 로그 데이터 중앙화
      • 효율적인 로그 처리 및 문제 원인 추적
    • ELK 스택 연동
      •  Elasticsearch, Logstash, Kibana와 통합
      • 실시간 로그 분석 및 검색 시스템 구축
      • 활용 : 실시간 로그 모니터링, 즉각적인 문제 해결
    • 기술 스택 연동
      • 카프카 스트림스 : 실시간 데이터 변환 및 이벤트 처리
      • Apache Flink, Spark Streaming : 고급 실시간 데이터 처리
    • 마이크로 서비스 아키텍쳐
      • 서비스 간 비동기 통신
        • 마이크로서비스 간 이벤트 기반 아키텍쳐 지원
        • 확장성과 유연성 제공
      • 확장 가능한 이벤트 드레이븐 시스템
        • 대규모 서비스에서 고성능 비동기 통신 지원 (전자상거래, 결제, 배송)
    • 데이터 파이프라인
      • 데이터 수집 및 변환
        • 여러 소스에서 실시간 데이터 수집 및 중앙 집계
        • 다양한 분석 시스템으로 데이터 전당
      • Kafka Connect 활용
        • 다양한 데이터 소스와 연동 (실시간 데이터 파이프라인 구축
    • 금융 거래 처리
      • 실시간 금융 거래 처리
        • 대규모 트랜잭션 데이터 실시간 처리
        • 빠른 거래 처리 및 정확한 데이터 분석
      • Fraud Detection 시스템
        • 실시간 거래 데이터 분석을 통한 분석 처리
    • 미디어 스트리밍 서비스
      • 실시간 미지어 데이터 처리
        • 스트리밍 데이터 처리 및 빠른 콘텐츠 전송
        • 맞춤형 추천 및 미디어 품질 최적화
      • 실시간 분석을 통한 품질 최적화
        • 사용자 행동 추적 및 서비스 문제 모니터링
    • 실시간 광고 배포 시스템
    • 클릭 스트림 분석

'Backend' 카테고리의 다른 글

카프카의 고급 기능  (0) 2025.02.13
Redis 개념  (0) 2025.02.09
시스템 확장  (0) 2025.02.08
분산 시스템  (0) 2025.02.03
대규모 트래픽 처리  (0) 2025.02.03

소트 연산이 불가피하다면 메모리 내에서 처리를 완료할 수 있도록 노력해야한다.

Sort Area를 늘리는 것도 좋지만. Sort Area를 적게 사용할 방법부터 찾아야한다.

 

소트 데이터 줄이기

1번은 가공한 결과집합을 Sort Area에 담지만 2번은 가공하지 않는 상태로 정렬을 완료한다. 2번이 적게 든다

 

소트한 데이터량이 다르므로 2번이 훨씬 적게 했다.

 

Top N 쿼리의 소트 부하 경감 원리

인덱스로 소트 연산을 생략할 수 없을때, Top N 쿼리가 어떻게 작동할까

인덱스로 소트 연산을 생략할 수없어 Table Full Scan 방식으로 처리

실행계획에 Sort Order By 가 있다. Table Full Scan 대신 종목코드가 선두인 인덱스를 사용할 수도 있지만, 바로 뒤 컬럼이 거래일시가 아니면 소트 연산을 생략할 수없으므로 Sort Order By가 나타난다.

Stopkey가 있는걸 보아 Top N 소트 알고리즘이 작동한다. -> 소트 연산 횟수와 Sort Area 사용량을 최소화한다.

  1. 처음 10개 레코드를 거래일시 오름차순으로 정렬해서 배열에 다믄ㄴ다
  2. 이후 읽는 레코드에 대해서는 배열 맨 끝에 있는 값과 비교해서 그보다 작은 값이 나타날때만 배열에서 다시 정렬한다. 기준에 맨 끝에 있던 값은 버린다.

이렇게 하면 오름차순으로 최소값을 갖는 열 개 레코드를 찾아낼 수 있다.

AutoTrace에서 pr과 pw가 전혀 발생하지않음

 

Top N 쿼리가 아닐때 발생하는 소트 부하

실행계획에서 Stopkey가 사라졌다. 알고리즘이 작동하지않고 pr과 pw도 발생했다.

 

분석함수에서의 Top N 소트

윈도우 함수 중 rank나 row_number 함수는 max함수보다 소트 부하가 적다. 알고리즘이 발동하기 때문

pr pw발생

max대신 rank를 사용하면

적게 발생한다.

'SQLP > SQLP' 카테고리의 다른 글

6-1, DML 기본 튜닝 (2)  (0) 2025.02.21
6-1. 기본 DML 튜닝 (1)  (0) 2025.02.20
5-3. 인덱스를 이용한 소트 연산 생략  (0) 2025.02.09
5-2. 소트가 발생하지 않는 SQL 작성  (0) 2025.02.02
5-1. 소트 연산 이해  (0) 2025.02.01

+ Recent posts