이 글은 'Fundamentals of Database Engineering'에 관한 아래 유데미 강의를 보고, 공부한 내용을 정리하였습니다.
https://www.udemy.com/course/database-engines-crash-course
테이블과 인덱스가 저장되는 방식
논리적 테이블 -> 열과 행(혹은 document)으로 이뤄져 있음
Row_ID
- 특정 행 ID를 고유하게 식별(Postgres에서는 tuple ID)
- MySQL에서는 기본 키가 사실상 가짜(sudo) 행 ID가 됨, 다른 DB에서는 별개의 새로운 행 ID가 열에 생성됨
Page
- 행은 논리적 페이지에 저장됨, 기술적으로 한 페이지에 많은 행이 들어갈 수 있음
- 페이지는 고정된 크기(MySQL는 16kb)의 메모리 위치로, 디스크 위치로도 변환되는 일련의 바이트
- 디스크는 RAM처럼 특정 ID의 행만 읽을 수 없음. 디스크는 페이지를 읽음.
- IO를 실행하면 하나 이상의 페이지를 얻게됨(단, 이건 HDD/SSD 포멧 방식 등에 영향을 받음)
- 예를 들어 페이지에 3개의 row가 저장될 수 있다면 1000개의 row는 page 0~333에 저장되는 방식
ㄴ 쿼리 속도에 영향을 줌
+ 페이지 크기: 소형 페이지는 페이지 크기가 미디어 블록 크기와 비슷할 경우 RW가 더 빨라지지만, 페이지 헤더 메타데이터의 오버헤드 비용이 높아질 수 있음. 대형 페이지의 경우 메타데이터 오버헤드와 페이지 분할이 최소화되지만 느리고 읽기 및 쓰기 비용이 높아짐
IO
- IO는 디스크를 읽는 요청을 하는 것
- IO를 줄일 수록 쿼리가 빨라짐
- IO는 단일 행을 읽는게 아닌 여러 행이 담긴 페이지를 읽음
- OS에 따라 일부 IO는 OS 캐시로 이동(특히 Postgres는 운영 체제 캐시에 크게 의존함)
Heap
- 데이터 테이블을 가리키는 페이지의 모음
- 테이블 자체에 대한 모든 정보가 담겨있음
- 힙에서 데이터를 바로 찾으면 비용이 많이 듬. 그래서 인덱스가 필요한데, 인덱스는 힙에서 정확히 어떤 부분을 읽어야하는지 알려줌
Index
- 효과적으로 데이터를 가져올 수 있도록 힙으로 이동할 정확한 위치를 파악하는데 도움을 주는 것으로 포인터(행 ID를 가리키고 있음)를 갖고 있음
- 하나 이상의 열을 효과적으로 인덱싱할 수 있음.
- B-tree 라는 데이터 구조를 사용
- 인덱스도 페이지로 저장되며, 인덱스 항목을 가져오려면 IO 비용이 발생함
- 인덱스가 작을 수록 메모리에 fit하기에 빠르게 검색할 수 있음
Note
- 때로는 힙 테이블이 단일 인덱스를 기준으로 구성될 수 있음.
- 클러스터 인덱스 : 힙은 인덱스를 기준으로 정렬될 수 있음. 기본 키는 특별히 지정하지 않는 한 클러스터 인덱스로 취급됨(단, Postgres의 기본 키는 보통 보조 키여서 해당되지 않지만, MySQL의 경우 항당 기본 키를 가져서 클러스터형 인덱스를 가지고 있음
- 데이터 타입에도 유의해야하는데, 예를들어 클러스터 인덱스에 UUID를 사용하는 것은 쓰기 성능을 저하시킴. UUID를 기본 키로 쓰면, 힙은 무작위 UUID를 기준으로 구성되는데, 연속되지 않고 무작위 page에 행이 들어가기 때문에 많은 비용을 발생시킴킴
행 기반 vs 열 기반 DB
행 기반 DB
- 테이블이 디스크에 행으로 저장됨
- HDD/SSD에서 block 단위로 IO read를 하게 되는데, 여러 행을 한 블록에서 가져올 수 있음
- 읽기 과정에서 필요없는 열을 가져오면서 많은 낭비된 읽기가 발생
- 무언가를 찾은 후 추가 열을 요청하는 것은 저렴함
열 기반 DB
- 테이블이 디스크에 열로 저장됨
- 각 열별로 모든 값을 가져와서 연속된 값으로 디스크에 저장함
- 저장될 때, 행 ID가 열(블록)마다 중복되게 됨
- 각 열은 1개 이상에 블록에 나눠서 저장되게 됨
장단점
- 행 기반 : RW에 최적화, OLTP(온라인 트랜잭션 작업), 압축/집합 효과적이지 않음, 다중 열에서 효과적 쿼리
- 열 기반 : 쓰기가 느림, OLAP(온라인 분석 작업), 단일 열 압축/집합, 집계작업에 효과적임
기본 키 vs 보조 키
기본적으로 행에서는 순서를 강제하지 않음. 데이터는 힙이라고 불리는 디스크에 특정 공간에 저장됨
기본 키(primary key)
- 기본 키의 개념이 추가되면 테이블에 클러스터링이라는 작업을 수행 함.
* 클러스터링 : 그 키를 중심으로 테이블을 구성하는 개념. 즉, 순서가 생기는 것이고, 순서와 관련된 추가 비용이 발생하는 것. 테이블 자체의 인덱스라고 볼 수 있음.(클러스터형 인덱스 혹은 IOT(인덱스로 조직화된 테이블)이라함)
- 추가 비용이 발생함에도, 클러스터형 인덱스는 범위 쿼리에서 속도가 빨라지는 장점이 있음
- 만약 기본키가 랜덤으로 있다면, 무작위성 때문에 힙을 왔다갔다하게 됨. DB가 이러한 행을 삽입하기 위해 수행하는 메모리 캐싱의 이점을 누릴 수 없게됨.
보조 키
- 보조키는 자체적으로는 아무 순서도 없지만, 다른 구조에서 순서가 있음. 즉, 인덱스를 위한 별도의 구조를 유지하고 있는 것(보조 인덱스)
- 검색 시에는 먼저 이 인덱스로 이동해서 검색을 수행하고, 원하는 튜플이나 페이지를 수집해야함(인덱스 자체에서는 모든 정보를 포함하지 않기 때문)
- 단, 이 방식을 사용하면 인덱스에서 찾고 실제 data를 얻기 위해서 이동을 해야되서 비효율이 발생할 수 있음.