개요
- 이번 글에서는 PostgreSQL의 Logical Structure에 대해서 정리해보려고 한다.
- DBMS마다 약간씩 Structure가 다르기 때문에 이번 글에서는 PostgreSQL에 초점을 맞춰서 설명해 보려고 한다.
PostgreSQL Logical Structure
PostgreSQL Logical Structure를 정리하면 아래와 같다.
이제 각각의 구성요소에 대해서 정리해 보자.
데이터베이스 클러스터
- PostgreSQL은
여러 개의 데이터베이스와 Role, 테이블스페이스의 집합
이다. - 각 클러스터는 고유한 포트 번호와 시스템 카탈로그를 가지며, 서로 다른 클러스터의 데이터베이스들은 독립적으로 작동한다.
- 데이터베이스 클러스터가 생성되면
PGDATA
라는 환경변수가 생기는데, 해당 환경변수에 담긴 경로가Base 디렉토리
가 된다.
- Base 디렉토리에는 아래와 같은 파일들이 존재한다.
- 또한, Base 디렉토리에는 아래와 같은 디렉토리가 존재한다.
데이터베이스
- PostgreSQL에서 데이터베이스는
Schema의 집합
이다. - PostgreSQL 초기화 시(initDB),
\l
명령어를 치면 아래와 같이 3개의 데이터베이스가 기본적으로 생성되어 있다.
- 데이터베이스는 $PGDATA/base 디렉토리에 저장되어 있다.
- 위 사진에서 1, 4, 5와 같은 디렉토리명은 데이터베이스의 OID이다. (이 부분은 뒤에서 좀 더 살명한다.)
- 위 3개의 데이터베이스의 역할은 아래와 같다.
- template1
시스템 표준 데이터베이스
(Standard System Database)이다.- 새로운 데이터베이스를 생성할 때
기본 템플릿
으로 사용되는 데이터베이스다. - 데이터베이스를 신규로 생성 시 template 옵션을 따로 주지 않으면 template1을 복제하여 생성한다.
- template1은 사용자에 의한 변경 및 접속이 가능하다.
- template0
원시 데이터베이스
(Pristine Database)이다.- template0은 template1과 유사하게 새 데이터베이스의 템플릿으로 사용되지만,
수정되지 않은 상태를 유지
하는 데 사용된다. - template0은 주로 template1이 사용자에 의해 변경되었을 때
원래 상태로 새 데이터베이스를 생성하는 데 사용
된다.
- postgres
- postgres 데이터베이스는 template1 데이터베이스를 이용해서 생성된 기본 데이터베이스이다.
- 접속 시
데이터베이스를 지정하지 않으면 postgres 데이터베이스로 접속
된다.
- 그럼 한번 template1 데이터베이스에 테이블을 생성해 보자.
- template1 데이터베이스에 test_tb라는 테이블을 만들었다.
- 그리고 test_db라는 테이블을 만들었다.
- 그렇게 되면 template1로 test_db가 생성되기 때문에 test_db에도 test_tb라는 테이블이 만들어져 있는 것을 확인할 수 있다.
테이블스페이스
- PostgreSQL 서버가 설치되면
pg_default
와pg_global
테이블스페이스가 생성된다. - 아래와 같이 쿼리를 통해서도 확인해 볼 수 있다.
- 테이블 생성 시에 테이블스페이스를 지정하지 않으면 pg_default 테이블스페이스에 테이블이 저장된다.
데이터베이스 클러스터 레벨
에서 관리되는 테이블은 pg_global 테이블스페이스에 저장된다.- pg_default 테이블스페이스의 물리적 위치는
$PGDATA/base
이고 pg_global 테이블스페이스의 물리적 위치는$PGDATA/globl
이다.- 따라서
$PGDATA/base
하위에 존재하는 데이터베이스들은 모두 pg_default라는 테이블스페이스를 사용하고 있는 것이다. $PGDATA/base
하위에는 테이블, 인덱스, 뷰, 시퀀스, 함수와 같은 오브젝트가 실제로 저장되는 공간이며, 저장경로는$PGDATA/base/{database_oid}/{object_oid}
로 구성된다.
- 따라서
- 1개의 테이블스페이스를 여러 개의 데이터베이스가 사용할 수 있다. 이때,
테이블스페이스 디렉토리 내에 데이터베이스별로 서브 디렉토리가 생성
된다. - 따라서 해당 파일시스템은 PostgreSQL의 시스템 사용자(OS User)가 소유해야 한다. (
읽기/쓰기 권한
) - 테이블스페이스 생성 시 위치를 지정할 수 있다. 이러한 점을 활용하면
성능 최적화
를 할 수도 있다.- 예를 들어, 자주 사용되는 오브젝트는 SSD에 위치시키고 자주 사용되지 않는 오브젝트는 Disk에 위치시킬 수 있다.
사용자 테이블스페이스
를 생성하게 되면$PGDATA/tblspc
디렉토리에 사용자 테이블스페이스와 관련된 심볼릭 링크가 생성된다.- 테이블스페이스를 생성하는 User(Role)이 테이블스페이스의 Owner가 되며, 생성 시
Owner를 지정
할 수 있다.
Role
- PostgreSQL에서 Role은 데이터베이스
사용자 또는 그룹의 권한들을 특정 이름으로 모아둔 것
이다. - PostgreSQL에서는
USER = ROLE
이라고 생각하면 된다. - Role은 데이터베이스 레벨이 아닌
클러스터 레벨
에서 공통으로 사용된다. - Role은 오브젝트를 소유할 수 있으며, 오브젝트에 대한 권한 처리를 할 수 있다.
- Role 삭제 시 Role이 소유한 오브젝트에 대한 처리가 필요하다.
- Role의 종류는 아래와 같다.
Role Type | Description |
---|---|
SUPERUSER | 데이터베이스 시스템의 모든 권한을 가지며, 보안 제약을 무시할 수 있는 역할 |
LOGIN | 데이터베이스에 로그인할 수 있는 권한을 가진 역할 |
CREATEDB | 새로운 데이터베이스를 생성할 수 있는 권한을 가진 역할 |
CREATEROLE | 새로운 역할을 생성할 수 있는 권한을 가진 역할 |
NOLOGIN | 로그인이 불가능한 역할, 주로 그룹 역할로 사용 |
REPLICATION | 데이터베이스 복제를 수행할 수 있는 권한을 가진 역할 |
BYPASSRLS | 행 수준 보안 정책을 무시할 수 있는 권한을 가진 역할 |
INHERIT | 부모 역할의 권한을 상속받는 기능 |
CONNECTION LIMIT | 역할에 대한 동시 데이터베이스 연결 수 제한 |
PASSWORD | 역할 로그인에 사용되는 비밀번호 |
Schema
- PostgreSQL에서 스키마는
Object의 집합
이며 일종의 네임스페이스 역할을 한다. - 하나의 데이터베이스는 여러 개의 스키마를 가질 수 있다.
- public 스키마는 기본으로 제공되는 스키마이며 모든 권한이 부여된 스키마다.
- PostgreSQL에서의 스키마는 Oracle의 스키마와 아래와 같은 차이점이 있다.
- Oracle에서 스키마는 특정 사용자 계정에 바인딩된다.
- 사용자 계정이 생성되면 해당 사용자의 스키마도 함께 생성되며 이 사용자는 스키마의 소유자가 되며, 스키마 내의 모든 오브젝트를 관리한다.
- 즉, Oracle에서는 Owner = Schema 로 인식된다.
- 하지만 PostgreSQL에서의 스키마와 사용자(또는 데이터베이스 역할)가 직접적으로 연결되지 않는다.
- 따라서 사용자가 여러 스키마를 소유할 수 있으며, 하나의 스키마는 여러 사용자에 의해 공유될 수 있다.
- PostgreSQL에서의 스키마의 장점은 아래와 같다.
- 여러 사용자가 서로 간섭 없이 하나의 데이터베이스를 사용할 수 있다.
- 관련된 데이터와 오브젝트를 스키마별로 나누어 관리함으로써, 시스템의 복잡성을 줄이고 유지보수를 용이하다.
- 동일한 데이터베이스 내에서 동일한 이름의 오브젝트를 여러 개 만들 수 있다.
- 스키마별로 다른 사용자 또는 역할에게 다른 접근 권한을 부여해서 데이터베이스 보안을 강화하고, 접근을 세밀하게 제어할 수 있다.
오브젝트
- PostgreSQL에서 오브젝트는 데이터를 참조하거나 저장하기 위해 사용되는 객체를 말한다.
- 오브젝트의 타입에는 Tables, Views, Indexes, Sequences, Functions, Triggers, Domains, Schemas, Materialized Views, Foreign Keys 등이 있다.
- 또한, 데이터베이스에 포함된 오브젝트들은 아래와 같이 pg_class에서 조회할 수 있다.
SELECT oid AS OID, relname AS object_name, relkind AS object_type
FROM pg_class
WHERE relname = 'test_tb' AND relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'public');
- 여기서 relkind 값에는 오브젝트의 타입 정보가 담긴다. 대표적으로 쓰이는 값들은 아래와 같다.
Object Type | relkind |
---|---|
Tables | r |
TOAST Tables | t |
Views | v |
Indexes | i |
Sequences | S |
Materialized Views | m |
Composite Types | c |
Foreign Tables | f |
Partitioned Tables | p |
Partitioned Indexes | I |
- PostgreSQL의 오브젝트들은 각각 oid(Object Id)를 가지고 있으며, oid를 이름으로 하는 파일로 자신이 속한 데이터베이스의 디렉토리에 저장된다.
- pg_database, pg_class 테이블에서 데이터베이스의 oid와 테이블의 oid를 확인할 수 있다.
ls $PGDATA/base/{데이터베이스의 OID}/ | grep {테이블의 OID}
를 통해서 데이터베이스 디렉토리에 해당 테이블이 있는지 확인해 보면 아래와 같다.
- 또한 Tables 오브젝트는 테이블 별로 3개의 파일이 존재한다.
- 실제로
$PGDATA/base
디렉토리에서 데이터베이스 내의 파일들을 보자.
- OID(Object ID): 테이블
데이터를 저장
하기 위한 파일이다. - OID_fsm: 테이블
여유 공간을 관리
하기 위한 파일이다. - OID_vm: 테이블
블록의 visibility
를 관리하기 위한 파일이다. - 테이블도 아래에서 설명할 오브젝트의 일종이다.
References
'Database' 카테고리의 다른 글
인덱스를 활용한 Sort 오퍼레이션 생략하기 (With PostgreSQL) (0) | 2023.12.27 |
---|---|
PostgreSQL의 메모리 레이아웃과 데이터를 읽어오는 과정 (0) | 2023.12.19 |
PostgreSQL 아키텍처 이해하기 (0) | 2023.12.08 |
서브쿼리 변환하기 2편 (With Java, QueryDSL) (0) | 2023.11.26 |
서브쿼리 변환하기 1편 (이론) (0) | 2023.11.26 |