Innovating today, leading tomorrow

OpenSQL_Internals
[OpenSQL] PostgreSQL의 데이터 레이아웃

[OpenSQL] PostgreSQL의 데이터 레이아웃

데이터 레이아웃

데이터베이스 클러스터

PostgreSQL의 데이터베이스 클러스터는 하나의 PostgreSQL 서버가 관리하는 데이터베이스들의 모음입니다.

A database cluster is a collection of databases that is managed by a single instance of a running database server.
– PostgreSQL 공식 문서 –

데이터베이스 클러스터를 새로 생성하면 앞으로 데이터를 저장하고 관리하기 위한 Base 디렉토리가 생성되며, PGDATA 환경변수에 Base 디렉토리의 경로가 저장됩니다. 앞으로는 Base 디렉토리의 경로를 PGDATA라 지칭하겠습니다. Base 디렉토리에는 다음과 같은 파일들과 디렉토리들이 기본적으로 생성됩니다.

Files in base directory

Files설명
PG_VERSIONPostgreSQL의 major version number가 들어있는 file
pg_hba.confClient 인증정보를 제어하는 file
pg_ident.confOS user와 PostgreSQL user의 mapping 정보를 제어하는 file
postgresql.confPostgreSQL 설정 parameter를 저장하는 file
postgresql.auto.confALTER SYSTEM 문으로 설정되는 parameter를 저장하는 file
postmaster.optsPostgreSQL server가 기동된 command line을 기록하는 file

Directories in base Directory

directories설명
base/Database subdirectory가 들어있는 subdirectory
global/pg_database나 pg_control 같은 cluster-wide table이 들어있는 subdirectory
pg_commit_ts/Transaction commit timestamp data가 들어있는 subdirectory
pg_dynshmem/Dynamic shared memory subsystem이 사용한 file을 저장하는 subdirectory
pg_logicalLogical decoding을 위한 상태 정보를 담는 subdirectory
pg_multixactMultitransaction의 상태 정보를 담는 subdirectory
pg_notifyLISTEN/NOTIFY 상태 정보를 담는 subdirectory
pg_repslotReplication slot data를 담는 subdirectory
pg_serialCommit된 serializable transaction 정보를 담는 subdirectory
pg_snapshotspg_export_snapshot 함수를 통해 export된 snapshot을 저장하는 subdirectory
pg_statStatistics collector process가 영구 저장하는 file을 담는 subdirectory
pg_stat_tmpStatistics collector process가 임시 저장하는 file을 담는 subdirectory
pg_subtransSubtransaction 상태 정보를 담는 subdirectory
pg_tblspcTablespace에 대한 symbolic link를 담는 subdirectory
pg_twophasePrepared transaction의 상태 정보를 담는 subdirectory
pg_walWAL segment file을 저장하는 subdirectory
pg_xactTransaction의 commit 상태 정보를 담는 subdirectory

데이터베이스

PostgreSQL의 데이터베이스는 오브젝트(aka. SQL 오브젝트, 데이터베이스 오브젝트)들을 관리하기 위한 최상위 계층(Top-most hierarchy)입니다.

Databases are therefore the topmost hierarchical level for organizing SQL objects (“database objects”).
– PostgreSQL 공식 문서 –

PostgreSQL의 데이터베이스는 PostgreSQL의 명령행 도구(Command Line Tool)인 psql에서 “l” 명령어를 통해 조회할 수 있습니다. 설치 직후, 데이터베이스 목록을 조회해보면, postgres, template0, template1 데이터베이스를 포함하고 있음을 확인 할 수 있습니다.

example=# l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
———–+————-+————-+—————+————-+——————————-
postgres | postgres | UTF8 | en_US.utf8 | en_US.utf8
| template0 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres +
| | | | | | postgres=CTc/postgres
(3 rows)

각각의 데이터베이스는 $PGDATA/base 디렉토리에 저장되어 있습니다. 하단의 예시는 초기 상태의 디렉토리입니다. 하단의 예시의 디렉토리들은 순서대로 각각 postgres, template0, template1 데이터베이스에 대한 디렉토리입니다. 또한 psql에서 조회한 데이터베이스 목록과 맵핑되는 것을 확인할 수 있습니다.

root@a4ac31d234ff:/# ls $PGDATA/base
1 13756 13757

1, 13756, 13757은 각각 postgres, template0, template1 Database에 대한 디렉토리입니다. 각 기본 데이터베이스들의 역할은 다음과 같습니다.

  • postgres는 유저, 유틸리티, 외부 툴 등에서 사용하기 위한 기본 데이터베이스입니다.
  • template1은 시스템 표준 데이터베이스(Standard System Database)입니다. CREATE DATABASE를 수행하여 새로운 데이터베이스를 생성할 경우, 일반적으로 template1을 복제하여 생성하게 됩니다. template1은 사용자에 의한 변경 및 접속이 가능합니다.
  • template0은 원시 데이터베이스(Pristine Database)이며 PostgreSQL에서 정의한 기본 데이터베이스입니다. template1의 구성을 사용하고 싶지 않다면 “TEMPLATE template0” 옵션으로 template0을 복제하도록 할 수 있습니다. template0은 사용자에 의한 변경 및 접속이 불가능합니다.

Reference.
https://www.postgresql.org/docs/current/app-initdb.html
데이터베이스와 Base 디렉토리의 연관성을 실제로 확인하기 위하여 psql에서 다음과 같이 CREATE DATABASE 명령을 실행해보겠습니다.

$ CREATE DATABASE EXAMPLE;

수행 후, 새로 생성한 EXAMPLE 데이터베이스에 해당하는 16384 디렉토리가 $PGDATA/base에 생성된 것을 확인할 수 있습니다.

root@a4ac31d234ff:/# ls $PGDATA/base/
1 13756 13757 16384

해당 16384 내에는 기본적인 오브젝트 파일들이 생성되어 있습니다. 해당 오브젝트 파일들은 다른 데이터베이스 디렉토리에도 공통적으로 생성되어 있으며, pg_class 등 모든 데이터베이스에서 공통적으로 조회가 가능한 오브젝트들임을 확인할 수 있습니다. 해당 디렉토리 내부의 오브젝트 파일에 대해서는 후술할 오브젝트 문단에서 설명하겠습니다.

오브젝트

DBMS(Postgres의 데이터베이스와 구분하기 위하여 DBMS로 설명)에서 오브젝트에 대한 일반적인 정의는 데이터를 참조하거나 저장하기 위해 사용되는 객체들입니다.
References.
https://www.techopedia.com/definition/24081/database-object
https://www.ibm.com/docs/en/db2/10.5?topic=concepts-database-objects
https://www.geeksforgeeks.org/database-objects-in-dbms/
https://www.w3schools.blog/database-objects-dbms

여타의 데이터베이스와 마찬가지로 PostgreSQL 역시 오브젝트 개념을 포함하고 있습니다. PostgreSQL은 TABLE, INDEX, SEQUENCE, VIEW, FUNCTION 등의 오브젝트 타입을 제공하고 있습니다. PostgreSQL에서 데이터베이스에 포함된 오브젝트들은 pg_class에서 조회할 수 있습니다.

PostgreSQL의 오브젝트들은 각각 oid(Object Id)를 가지고 있으며, 각각의 오브젝트는 oid를 이름으로 하는 파일로 자신이 속한 데이터베이스의 디렉토리에 저장됩니다.

각 데이터베이스를 의미하는 디렉토리의 내부에는 데이터베이스에서 관리하는 오브젝트들의 파일들이 포함되어 있는 것을 확인 할 수 있습니다. 이를 실제로 확인하기 위하여 psql에서 다음과 같은 예시를 실행해보겠습니다.

$ c example — connect to ‘example’ database
$ CREATE TABLE EXAMPLE_TABLES (user_id serial PRIMARY KEY);

예시에서는 추가로 EXAMPLE_TABLES라는 테이블을 생성해보았습니다. 실제로 16384 디렉토리에서 16385, 16386, 16390이라는 파일이 추가로 생성되었음을 확인할 수 있습니다.

.fsm(free space map)과 .vm(visibility map) file은 이후 Chapter에서 설명하겠습니다.

root@a4ac31d234ff:/# ls $PGDATA/base/16384
..
16385 16386 16390
..

해당 파일의 이름(oid)로 pg_class를 조회해보면 실제로 다음과 같은 오브젝트들이 생성된 것을 확인 할 수 있습니다.

example=# select oid, relname from PG_CLASS where oid=16385 or oid=16386 or oid=16390;
oid | relname
——-+—————————-
16385 | example_tables_user_id_seq # Sequence (Serial)
16386 | example_tables # Table
16390 | example_tables_pkey # Primary Key
(3 rows)

스키마

PostgreSQL의 스키마는 오브젝트들을 포함하고있는 일종의 네임스페이스입니다.

In PostgreSQL, a schema is a namespace that contains named database objects such as tables, views, indexes, data types, functions, stored procedures and operators.
– PostgreSQL 공식 문서 –

스키마의 유용성은 다음 사례를 통해 유추할 수 있습니다.

  • 여러 사용자가 서로 간섭 없이 하나의 데이터베이스를 사용할 수 있도록 합니다.
  • 각 오브젝트를 논리적 그룹으로 구성하여 관리 할 수 있도록 합니다.
  • 외부 어플리케이션을 스키마 분리하여 오브젝트간 이름 충돌(중복)을 방지할 수 있습니다.

테이블스페이스

PostgreSQL의 테이블스페이스는 오브젝트들을 저장하는 파일 시스템 내 위치를 직접 지정할 수 있도록 합니다. 즉, 데이터베이스의 디렉토리가 아닌 외부에 오브젝트 파일을 저장할 수 있습니다.

Tablespaces in PostgreSQL allow database administrators to define locations in the file system where the files representing database objects can be stored.
– PostgreSQL 공식 문서 –

테이블스페이스의 유용성은 다음 두 가지 사례를 통해 유추할 수 있습니다.

  • 파티션이나 볼륨의 공간이 부족해 확장할 수 없는 경우 다른 곳에 테이블스페이스를 생성해 재구성 전까지 사용할 수 있습니다.
  • 각 객체의 사용 패턴을 바탕으로 한정된 디스크 자원을 효율적으로 할당함으로써 성능을 최적화 할 수 있습니다.

테이블스페이스를 생성하게 되면 PGDATA/pg_tblspc 디렉토리에 심볼릭 링크로 저장됩니다. 해당 심볼릭 링크는 테이블스페이스 생성 시 지정한 위치를 가리킵니다. 해당 위치에는 규칙에 따라 명명된 이름의 디렉토리가 생성됩니다. 이후 테이블스페이스에 오브젝트를 생성하게 되면 생성된 디렉토리 내부에 {databas}/{object_oid} 경로에 해당 오브젝트의 파일이 생성됩니다.

example=# CREATE TABLE newtbl (…..) TABLESPACE new_tblspc;
example=# SELECT pg_relation_filepath(‘newtbl’);
pg_relation_filepath
———————————————
pg_tblspc/16386/PG_14_202011044/16384/18894

Reference.
https://www.interdb.jp/pg/pgsql01.html

페이지 레이아웃 (파일 구조)

해당 문단에서는 PostgreSQL의 테이블과 인덱스에서 사용하는 페이지 포맷에 대해 설명하겠습니다.

This section provides an overview of the page format used within PostgreSQL tables and indexes.

PostgreSQL은 데이터를를 파일에 저장할 때, 페이지라고 하는 고정 크기(default: 8KB)의 영역들로 나누어 저장합니다. 각 페이지의 고정 크기를 변경하기 위해서는 PostgreSQL의 소스를 컴파일 하기 전, Config 수정이 필요합니다. 페이지의 고정 크기는 최대 32KB까지 변경할 수 있다. Config 수정을 위한 스크립트는 다음과 같습니다.

postgres/configure –with-blocksize={BLOCK_SIZE in KB}

파일의 크기는 다음과 같은 규칙에 의해 증가합니다. (if. BLOCK_SIZE = 8)

  • File의 최초 크기는 0KB입니다.
  • 이후 File의 크기는 적재한 데이터의 크기에 따라 8KB 배수 단위로 증가합니다.

즉, PostgreSQL은 필요한 파일의 크기를 페이지 단위로 확장합니다.

파일의 각 페이지는 Page Header, ItemIdData, Free Space, Items, Special Space로 구성되어 있습니다.

  • Page Header는 페이지에 대한 일반적인 정보를 담고 있으며, 페이지의 시작 부분에 위치합니다. Page Header는 PageHeaderData struct로 구현되어 있습니다.
  • ItemIdData는 Item의 구분자들의 Array이며, 각각 Item의 위치(offset)와 크기(size)를 담고있습니다. 해당 영역은 Page Header의 다음 위치입니다. ItemIdData는 ItemIdData struct로 구현되어 있습니다.
  • Items는 튜플 등 데이터, 데이터 레코드를 담고있습니다. ****ItemIdData의 증가(할당)를 고려하여 페이지의 마지막부터 역방향으로 증가(할당)합니다. Item의 구조는 테이블이 포함하는 내용에 따라 상이합니다.
  • Free Space는 ItemIdData과 Items 사이의 아직 할당되지 않은 영역을 의미합니다.
  • Special Space는 각 Access Method에서 필요한 추가 정보를 저장하기 위한 공간입니다. Access Method에 따라 다른 데이터를 저장하고 있습니다.

페이지 레이아웃은 테이블, 인덱스 파일에서 사용하는 공통적인 구조를 의미합니다. 그리고 테이블, 인덱스(B-Tree, GIST, GIN, …) 등 타입, 데이터에 대한 접근 방식(Access Method)에 따라 페이지 레이아웃의 내용은 다르게 채워집니다. 다음 내용에서는 그 중 테이블을 기준으로 동작 예시를 설명하겠습니다.

테이블 파일 레이아웃

테이블 파일은 위의 그림과 같이 페이지 레이아웃을 구성하고 있습니다. Items에는 힙 튜플이라고 불리는 구조체가 포함되어 있고 Special Space는 활용하지 않습니다. 이를 기반으로 실제 새로운 데이터가 추가되었을 때와 데이터를 읽을 때 어떤 방식으로 동작하는지 알아보도록 하겠습니다.

쓰기

테이블 파일에 새로운 데이터를 쓰기 위해서는 현재 페이지의 공간이 충분한지 확인해야 합니다. Page Header에는 pd_lower, pd_upper라는 값을 포함하고 있습니다. 해당 값은 각각 라인 포인터의 끝 부분의 위치와 튜플의 끝 부분(역순)의 위치의 Offset입니다. 해당 정보를 활용하여 새로 들어온 튜플의 크기와 Free Space 공간의 크기(= pd_lower – pd_upper)를 비교하여 해당 페이지에 쓸 것인지 새로운 페이지를 만들어 그 곳에 쓸 것인지 결정합니다.

이후 pd_upper를 튜플의 크기만큼 앞당긴 값으로 갱신하고 해당 위치에 새로운 튜플을 기록합니다. 이후 라인 포인터도 마찬가지로 pd_lower를 갱신하고 새로 추가합니다.

읽기

테이블 파일을 읽는 방법은 크게 두 가지로 나눌 수 있습니다. 첫번째는 테이블 파일만을 활용하여 순차적으로 읽는 Sequential Scan이고 두번째는 인덱스 파일에서 대상이 되는 데이터의 인덱스 튜플 추출하고 해당 정보로 테이블 파일의 튜플을 바로 찾아가는 Index Scan입니다. 다음 그림은 각각 Sequential Scan과 Index Scan의 과정을 도식화한 것입니다.

이번 컨텐츠는 PostgreSQ의 데이터 레이아웃에 관해 알아보았습니다

다음 컨텐츠인 ‘PostgreSQL의 프로세스와 메모리 아키텍처’를 바로 이어서 확인해보세요!

광고성 정보 수신

개인정보 수집, 활용 목적 및 기간

(주)티맥스티베로의 개인정보 수집 및 이용 목적은 다음과 같습니다.
내용을 자세히 읽어보신 후 동의 여부를 결정해 주시기 바랍니다.

  • 수집 목적: 티맥스티베로 뉴스레터 발송 및 고객 관리
  • 수집 항목: 성함, 회사명, 회사 이메일, 연락처, 부서명, 직급, 산업, 담당업무, 관계사 여부, 방문 경로
  • 보유 및 이용 기간: 동의 철회 시까지

※ 위 개인정보 수집 및 이용에 대한 동의를 거부할 권리가 있습니다.
※ 필수 수집 항목에 대한 동의를 거부하는 경우 뉴스레터 구독이 제한될 수 있습니다.

개인정보의 처리 위탁 정보
  • 업체명: 스티비 주식회사
  • 위탁 업무 목적 및 범위: 광고가 포함된 뉴스레터 발송 및 수신자 관리
 

개인정보 수집 및 이용

개인정보 수집, 활용 목적 및 기간

(주)티맥스티베로의 개인정보 수집 및 이용 목적은 다음과 같습니다. 내용을 자세히 읽어보신 후 동의 여부를 결정해 주시기 바랍니다.

  • 수집 목적: 티맥스티베로 뉴스레터 발송 및 고객 관리
  • 수집 항목: 성함, 회사명, 회사 이메일, 연락처, 부서명, 직급, 산업, 담당업무, 관계사 여부, 방문 경로
  • 보유 및 이용 기간: 동의 철회 시까지

※ 위 개인정보 수집 및 이용에 대한 동의를 거부할 권리가 있습니다.
※ 필수 수집 항목에 대한 동의를 거부하는 경우 뉴스레터 구독이 제한될 수 있습니다.

개인정보의 처리 위탁 정보

  • 업체명: 스티비 주식회사
  • 위탁 업무 목적 및 범위: 광고가 포함된 뉴스레터 발송 및 수신자 관리
  •