Notice
Recent Posts
Recent Comments
Link
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

걸음마부터 달리기

DB-6/31 본문

카테고리 없음

DB-6/31

성추 2024. 7. 7. 11:02

먼저 데이터의 중복이란?

 

그냥 간단하게 하나의 속성에 여러 중복되는 값들이 오면 그게 중복이고 이러한 중복을 최대한 피하게 저장하게 모델링하는게 정규화

 

 

반정규화: 

정규화된 엔터티, 속성, 관계에 대해 시스템의 성능향상과 개발(Development)과 운영(Maintenance)의 단순화를 위해 중복, 통합, 분리 등을 수행하는 데이터 모델링의 기법을 의미한다. 협의의 반정규화는 데이터를 중복하여 성능을 향상시키기 위한 기법이라고 정의할 수 있고 좀 더 넓은 의 미의 반정규화는 성능을 향상시키기 위해 정규화된 데이터 모델에서 중복, 통합, 분리 등을 수행하는 모든 과정을 의미한다. (==정규화를 끝낸 엔터티들에 대해 일부로 중복을 허용하는 정규화를 반대하는 방향으로 다시 모델링하여 성능향상을 함) 

 

정규화를 통해 조회, 입력/수정/삭제에 대한 성능 향상을 기대하는데 막상 정규화로 테이블 다 쪼개놓은까 조회 성능이 오히려 떨어질 수 있음 .따라서 부분적인 반정규화를 통해 (함수적 종속성은 위배하지 않으면서 중복성만 증가) 조회 성능을 향상시키는 경우가 있다.

 

예시) 다른 테이블에서 조인하여 가져와야 할 칼럼을 기준이 되는 테이블에 중복하여 제거하지 않고 그냥 넣어버려서 SQL을 단순하게 처리하도록 

 

칼럼의 반정규화가 실제로 많이 쓰이니까 이쪽만 봐보겠다.

중복칼럼 추가) 서로 다른 테이블로 정규화하면서 쪼개놨으니 조인하면서 봐야할 데이터는 그냥 중복을 무릎쓰고 하나의 테이블에 칼럼을 추가하여 조인없이 해당 테이블만 조회하면 되게 구성함

 

파생칼럼 추가) 미리 계산하는게 왜 중복을 피하는거냐?? >> 미리 계산 안하면 쿼리가 올때마다 직접 트랜잭션 안에서 계산해야되는거고 미리 계산한 값을 칼럼에 두면 쿼리가 와도 그 칼럼에서 데이터값 조회하면 됨. 

Q. 아니 어차피 계산 칼럼을 추가하고 그 칼럼에 미리 계산하여 값 넣는것도 계산 자체는 중복 과정을 거치고 넣는거 아니냐??

A. 그렇긴한데 쿼리는 진짜 올때마다 새로 계산해야됨. 전에 한 계산 저장을 따로 안하니까... 근데 한번 쫙 다 계산해놓고 칼럼에 값으로 넣어두면 쿼리가 와도 다시 하진 않으니까

 

이력테이블 칼럼추가)

데이터가 변경될때마다 따로 이력테이블에 기입하는건 중복을 유도하는 과정임. 따라서 반정규화 과정이라고 할 수 있음

 

 

PK에 의한 칼럼추가) 

기본키를 설정하면 직접 인덱스를 만들지 않아도 DBMS가 자동적으로 기본키에 대해서 인덱스를 만들어버림. 

인덱스에서 찾을때는 복합키의 경우 A B C 에서 A로 우선 정렬, A 같은것끼리 B 정렬, A 와 B 모두 같은 것끼리 C 정렬하는 형식이다.

 

따라서 A , B , C가 복합키로 있으면 이것에 대한 인덱스를 만들어버림. 근데 이때 C 단일속성으로 조회하면 인덱스를 보고 찾게되는데 당연히 인덱스 순서는 선행칼럼 기준으로 매번 정렬되고 같은 경우에만 후행칼럼으로 정렬됨. 따라서 후행칼럼들은 고르게 분포되어있지 않아 오히려 더 조회 시간이 오래걸릴 수 있다. 따라서 그냥 인덱스에 없는 일반속성 칼럼으로 중복되어도 추가하여 인덱스에서 벗어나 검색하겠다는거

 

 

분산 DB 시스템에서의 성능 사례)

 

DB 가 커지다보니 분산을 해놓을수밖에 없고, 분산시스템에서는 조인 과정에서 추가 오버헤드가 발생하고, 서버 B에서 부서에 대한 정보를 볼려면 무조건 서버 A쪽에서 부서 테이블과 조인해야된다. 그러다보니 성능이 감소할 여지가 있다.

 

자주 사용하는 컬럼을 중복되는 컬럼(데이터)여도 그냥 연계테이블에 추가해버려서 다른 서버까지 가서 조인하는 비용을 줄였다. 반정규화과정이다.

 

대량 데이터발생에 따른 테이블 분할:

테이블에 대한 데이터 양이 너무 많거나 하나의 테이블에 칼럼이 무수히 많으면 디스크에 많은 블록을 차지하게 된다.

이는 한개의 블록에 저장되어야 성능측면에서 좋은 면과는 반대된다(칼럼 갯수 많을때).

 

또한 하나의 블록에 많은 트랜잭션 작업이 들어오면 이 또한 성능이 감소한다. (데이터양이 많을때)

 

따라서 이에 대한 성능 증가측면에서 수평분할(데이터 양을 한 테이블에서 여러개로 나눔) , 혹은 수직분할 (칼럼을 다른 테이블로 쪼개서 하나의 블록에 저장되게...) 방법이 있다.

 

하나의 테이블에 대량의 데이터가 존재하는 경우에는 인덱스의 Tree구조가 너무 커져 효율성이 떨어져 데이터를 처리(입력, 수정, 삭제, 조 회)할 때 디스크 I/O를 많이 유발하게 된다. 또한 한 테이블에 많은 수의 칼럼이 존재하게 되면 데이터가 디스크의 여러 블록에 존재하므로 인해 디스크에서 데이터를 읽는 I/O량이 많아지게 되어 성능이 저하되게 된다. 

 

인덱스 탐색과정 및 구조:

https://www.youtube.com/watch?v=iNvYsGKelYs

 

3줄 요약: 

Index는 특정 칼럼을 오름차순으로 정리하고 복사하여 튜플 위치를 포인터와 같이 저장한 것이다.

B+ 트리 구조를 띄며 리프노드에만 실제 데이터값과 포인터가 존재하고 나머지 노드들은 가이드라인을 제공한다.

리프노드들끼리도 연결되어있어 데이터 탐색이 더 빠르다.

 

 

칼럼이 엄청 많을때) 

 

저렇게 칼럼이 존나게 많으면 블록이 여러개로 쪼개서 들어가 추가적인 I/O 오버헤드가 발생할 수 있다. 따라서 자주 조회되는 칼럼들은 따로 테이블에 빼놔서 같은 블록 안에서 접근 가능하도록 한다.

 

 

데이터가 엄청 많을때)

수평분할이 필요함. 그 기준으로 Range Partition , List Partition , HASH Partition 

논리적으로는 하나의 테이블이지만 물리적으로는 정말 다른 테이블로 저장된다.

따라서 SQL의 FROM 절에는 하나의 테이블이 오지만, 실제로 DBMS가 데이터를 테이블에서 찾을때는 해당 분할된 테이블 중 알맞는 테이블에서 기존의 데이터 일부에서만 찾는다. (성능향상)

 

Range Partition : Range Partition은 데이터의 값이 특정 범위 내에 있는지에 따라 데이터를 파티션으로 나누는 방법

 

List Partition : List Partition은 데이터의 값이 특정 목록에 있는지에 따라 데이터를 파티션으로 나누는 방법 (==직접 특정값을 SQL로 줘서 걔네들끼지 파티션)

 

HASH Partition : Hash Partition은 해시 함수를 사용하여 데이터를 균등하게 분할하는 방법. 특정 값에 대한 검색 시, 해시 함수를 사용하여 해당 값이 저장된 파티션을 빠르게 찾을 수 있습니다. 이는 데이터 접근 속도를 향상시킨다.