1. DOCKER 다운로드 및 설치
•
DOCKER란?
◦
소프트웨어를 컨테이너 단위의 격리된 환경 안에서 실행하도록 해주는 오픈소스 가상화 플랫폼
◦
DOCKER를 사용해 리눅스 환경의 PG를 설치 할 수 있습니다.
•
DOCKER 다운로드(4.33 기준 / Windows 11기준)
•
DOCKER 설치(4.33 기준 / Windows 11 기준)
◦
다운로드 받은, Docker Desktop Installer 를 실행
◦
Use WSL2 instead of Hyper-v 부분 체크가 나오면 체크하고 설치를 진행합니다.
▪
WSL은 리눅스 커널을 직접 사용하여 Windows 상에서 리눅스 환경을 제공
▪
경량화되어 있으며, 리눅스와 Windows 간의 파일 시스템 통합이 용이
▪
주로 리눅스 개발 환경을 Windows에서 구현하려는 사용자에게 적합
▪
WSL 2는 Docker와 더욱 통합되어 있어, 리눅스 컨테이너를 더 효율적으로 실행
▪
WSL을 사용하려면 윈도우에 관련된 추가 설치가 필요할 수 있다.
▪
상황에 따라 WSL2 설치가 필요합니다. 아래 글을 참고해 진행합니다.
◦
설치 완료 후 host 파일 변경 복원 메시지 나올 수 있습니다.
▪
저는 복원 안하고 넘어갔습니다.
•
DOCKER 메뉴
◦
설치된 DOCKER는 윈도우즈 상의 Docker Desktop을 프로그램을 실행하거나,
▪
윈도우즈의 Command 창에서 Docker 명령어를 실행할 수도 있습니다.
◦
Docker Desktop 화면
▪
윈도우즈에서 Docker Desktop을 실행하면 다음과 같은 화면이 나옵니다.
•
Images
◦
어플리케이션 실행에 필요한 모든 파일과 코드, 설정의 패키지.
◦
pull 을 통해 Postgre 이미지를 다운로드 할 수 있다.
•
Containers
◦
이미지를 통해 만들어진 실행 가능한 어플리케이션
▪
pull을 통해 저장된 postgre 이미지를 실행하면 postgre 컨테이너가 만들어지고,
▪
만들어진 postgre 컨테이너에 접속해서 사용할 수 있다.
•
Volumes
◦
컨테이너와 독립적으로 존재하는 데이터 공간
◦
컨테이너에서 생성되는 데이터를 컨테이너 외부에 저장할 수 있다.
2. PostgreSQL 설치 및 시작
•
Docker의 Pull 명령어를 사용해 Postgresql 16.4 를 설치합니다.
1.
윈도우즈의 윈도우 버튼 클릭
2.
검색창에 cmd 입력
3.
명령 프롬프트를 선택해서 실행
•
cmd(명령 프롬프트) 창에서 다음 명령어를 실행합니다.
◦
docker pull postgres:16.4
◦
위 명령어를 실행하면 Linux(debian)의 PG 16.4 의 이미지를 Docker의 이미지로 다운로드(pull) 합니다.
•
pull로 다운로드한 이미지를 run 명령어로 실행해야 합니다.
◦
run 명령어는 이미지를 컨테이너로 만드는 것이기 때문에 pull 후에 한 번만 실행하면 됩니다.
◦
run은 이미지를 컨테이너로 만드는 것이므로, DBMS의 start/stop과는 다릅니다.
◦
아래의 명령어로 pull 해 놓은 이미지 리스트를 확인할 수 있습니다.
docker images
Shell
복사
▪
이미지가 정상적으로 pull 되었다면 아래와 같은 리스트를 확인할 수 있습니다.
◦
아래 명령어로 이미지를 run 합니다.
▪
run할 때 pg의 admin 계정인 postgres의 암호를 설정합니다.
•
postgres:16.4 이미지를 mypg라는 이름의 컨테이너로 생성합니다.
•
여기서는 암호를 1qaz2wsx로 설정했습니다. 각자 편한 암호를 사용합니다.
•
컨테이너 내부에서 사용 가능한 공유 메모리(/dev/shm)의 크기를 256MB로 설정
◦
실제 PG는 DEFAULT로 128MB만 사용. os자원에서 메모리를 사용할 수 있게 256mb로 잡는 것을 권장.
docker run -d --shm-size=256m -p 5432:5432 -e POSTGRES_PASSWORD=1qaz2wsx --name mypg postgres:16.4
Shell
복사
3. DBeaver로 PG 접속하기
•
docker run을 완료했다면, DBeaver와 같은 SQL Tool로 DB 접속이 가능합니다.
•
아래 그림을 참고해 PG에 접속합니다.
•
DBeaver로 PG에 접속해, SQL창을 열고 다음 SQL로 연습용 데이터베이스(startdbpg)를 생성합니다.
CREATE DATABASE startdbpg;
SQL
복사
•
디비버에 startdbpg로 접속하는 컨넥션을 축가합니다.
◦
PG는 MySQL처럼 특정 DB에 접속 후 DB를 변경할 수 없습니다.
◦
Dbeaver에서 새로운 컨넥션을 추가
◦
Database를 새로 만든 startdbpg로 설정한다.
•
새로 만든 컨넥션으로 DBeaver에 접속한 후에 아래 SQL로 확장팩 관련된 정보를 확인합니다.
SELECT * FROM pg_available_extensions; -- 설치 가능한 확장팩
SELECT * FROM pg_extension; -- 설치된 확장팩
SQL
복사
3. PG_HINT_PLAN 설치하기
•
PG는 힌트를 사용하기 위해서는 확장팩인 pg_hint_plan을 설치해야 합니다.
•
조금 복잡할 수 있습니다. 개인적으로 이렇게 복잡해서.. 나중에 관리가 될까 싶습니다.
•
아래 경로에서 pg_hint_plan rpm 파일을 다운로드 합니다.
◦
여기서는 pg_hint_plan16-1.6.0-1.el8.x86_64.rpm 파일을 다운로드했습니다.
•
다운로드 받은 파일을, C 드라이드에 mypg_upload 이란 폴더에 카피해놓습니다.
◦
다운로드 받은 파일을 PG 컨테이너에 올려야 하는데, 파일 단위가 아닌 폴더 단위로만 올릴 수 있습니다. 그러므로 폴더 하나에 다운로드한 rpm 파일 하나만 놓도록 합니다.
•
rpm 파일을 컨테이너에 업로드합니다.
◦
Docker Desktop을 사용해 rpm 파일을 업로드합니다.
1.
containers를 선택합니다.
2.
mypg 컨테이너를 선택합니다.
3.
Files를 선택합니다.
4.
tmp 디렉토리에 마우스 우클릭 후 import를 선택합니다.
a.
앞에서 만든 mypg_upload 폴더를 선택하면 해당 폴더 채로 컨테이너에 업로드가 됩니다.
b.
업로드된 폴더를 확인할 수 있습니다.
•
rpm 파일을 설치합니다.
◦
debian linux에서 rpm 을 직접 설치하는데 이슈가 있습니다.
◦
alien을 사용해 rpm을 deb 형태 파일로 변환후 설치해야 합니다.
1.
Docker Desktop에서 컨테이너에 진입해 Exec 메뉴를 클릭합니다.
a.
여기서 Linux Shell 명령어를 실행할 수 있습니다.
2.
아래 명령어들을 차례대로 하나씩 입력합니다.
apt update
apt install alien
alien -d /tmp/mypg_upload/pg_hint_plan16-1.6.0-1.el8.x86_64.rpm
dpkg -i pg-hint-plan16_1.6.0-2_amd64.deb
Shell
복사
•
apt install alien 과정에서 y/n을 물으면 y를 선택합니다.
•
alien 이후에 rpm 파일의 이름이 변경됩니다. _(언더바)가 -(대쉬)로 변경되니 주의하세요.
3.
계속해서 EXEC창에서 다음 명령어로 pg_hint_plan이 컨테이너에 잘 설치되어 있는지 확인합니다.
ls /usr/pgsql-16/lib/
Shell
복사
•
pg_hint_plan.so란 파일이 보여지면 정상 설치된 것입니다.
4.
설치된 파일을 정상적인 경로로 카피해서 옮깁니다.
•
제 환경에서는 설치된 확장팩 모듈들이 다음 경로에 존재합니다.
◦
/usr/pgsql-16/share/extension/
•
위 경로의 파일들을 아래 경로로 옮겨야 정상적으로 확장팩이 작동합니다.
◦
/usr/share/postgresql/16/extension/
◦
아마도, 확장팩 모듈이 설치되는 경로와 실제 컨테이너상의 확장팩 모듈의 경로가 상이한 것 같습니다.
◦
EXEC 창에서 다음 명령어로 설치된 확장팩 모듈들을 카피합니다.
1.
pg_hint_plan.so는 옮기지 않고 현재 경로에 그대로 둡니다.
2.
/usr/pgsql-16/share/extension 에 설치된 파일만 다른 곳으로 옮깁니다.
cp -a /usr/pgsql-16/share/extension/* /usr/share/postgresql/16/extension/
Shell
복사
•
pg_hint_plan을 PG의 conf 파일에 등록합니다.
◦
설치된 pg_hint_plan 모듈을 PG가 가동될 때 불러올 수 있도록 설정해야 합니다.
1.
컨테이너의 Files 메뉴를 선택
a.
var/lib/postgresql/data 폴더까지 내려갑니다.
2.
postgresql.conf 를 마우스 우클릭 후 Edit File을 선택합니다.
3.
아래 부분에 파일의 내용이 열립니다. shared_preload_libraries 부분의 주석을 제거하고 다음과 같이 수정합니다.
a.
기본 설치된 경로가 문제인지, 경로 없이 pg_hint_plan을 바로 설정하면 제대로 작동하지 않습니다.
shared_preload_libraries = 'pg_stat_statements, /usr/pgsql-16/lib/pg_hint_plan' # (change requires restart)
Shell
복사
4.
오른쪽 위에 저장 버튼을 누릅니다.
5.
컨테이너를 종료했다. 다시 시작합니다.
•
추가로, postgresql.conf (var/lib/postgresql/data) 에서 병렬 처리를 제한합니다.
◦
방금 위에서 수정한 postgresql.conf 파일을 다시 엽니다.(열려 있다면 바로 수정하면 됩니다.)
1.
max_parallel_workers_per_gather 부분을 찾아서 주석을 제거하고 값을 0으로 설정합니다.
2.
저장합니다.
3.
종료 후 다시 시작합니다.
max_parallel_workers_per_gather = 0 # limited by max_parallel_workers
Python
복사
4. PG_HINT_PLAN 작동 확인하기
•
DBeaver를 사용해 앞에서 생성한 startdbpg에 재접속합니다.
•
아래 SQL로 설치된 pg_hint_plan을 확인합니다.
SELECT * FROM pg_available_extensions WHERE name like '%pg_hint%';
SQL
복사
•
DBeaver에서 다음 명령어로 확장팩을 사용할 수 있도록 합니다.
◦
startdbpg에 접속해서 실행해야, startdbpg안에서 확장팩을 사용할 수 있습니다.
-- startdbpg에 확장팩 두 개를 설치합니다.
-- pg_hint_plan은 추가 설치한 내용.
-- pg_stat_statements는 기본 제공하는 확장팩(shared_preload에 추가해야 사용할 수 있음)
CREATE EXTENSION pg_hint_plan; -- 힌트 관련 확장팩
CREATE EXTENSION pg_stat_statements; -- SQL 성능 수집 확장팩
SQL
복사
•
다음 SQL을 차례대로 입력해 힌트가 작동하는지 확인합니다.
◦
힌트를 사용하지 않았을때는 Bitmap Index Scan를, 힌트를 사용한 경우에는 Index Scan이 작동합니다. 힌트로 인해 실행계획이 변경되므로 힌트가 작동함을 알 수 있습니다.
create table test(a varchar(10), c varchar(10));
create index test_x1 on test(a);
insert into test(a,c)values('abc','abc');
insert into test(a,c)values('aaa','a12');
insert into test(a,c)values('ccc','cba');
EXPLAIN
SELECT t1.*
FROM test t1
WHERE t1.a = 'abc';
-- 위 SQL의 실행계획
Bitmap Heap Scan on test t1 (cost=4.18..12.64 rows=4 width=76)
Recheck Cond: ((a)::text = 'abc'::text)
-> Bitmap Index Scan on test_x1 (cost=0.00..4.18 rows=4 width=0)
Index Cond: ((a)::text = 'abc'::text)
EXPLAIN
SELECT /*+ IndexScan(t1 test_x1) */
t1.*
FROM test t1
WHERE t1.a = 'abc';
-- 힌트를 사용한 SQL의 실행계획(IndexScan으로 변경됨)
Index Scan using test_x1 on test t1 (cost=0.15..20.22 rows=4 width=76)
Index Cond: ((a)::text = 'abc'::text)
-- 이후 데이터베이스 생서을 위해 test 테이블을 DROP 합니다.
DROP TABLE IF EXISTS test;
SQL
복사