bloat postgresql check query

  SELECT
    current_database(), schemaname, tablename, /*reltuples::bigint, relpages::bigint, otta,*/
    ROUND((CASE WHEN otta=0 THEN 0.0 ELSE sml.relpages::FLOAT/otta END)::NUMERIC,1) AS tbloat,
    CASE WHEN relpages < otta THEN 0 ELSE bs*(sml.relpages-otta)::BIGINT END AS wastedbytes,
    iname, /*ituples::bigint, ipages::bigint, iotta,*/
    ROUND((CASE WHEN iotta=0 OR ipages=0 THEN 0.0 ELSE ipages::FLOAT/iotta END)::NUMERIC,1) AS ibloat,
    CASE WHEN ipages < iotta THEN 0 ELSE bs*(ipages-iotta) END AS wastedibytes
  FROM (
    SELECT
      schemaname, tablename, cc.reltuples, cc.relpages, bs,
      CEIL((cc.reltuples*((datahdr+ma-
        (CASE WHEN datahdr%ma=0 THEN ma ELSE datahdr%ma END))+nullhdr2+4))/(bs-20::FLOAT)) AS otta,
      COALESCE(c2.relname,'?') AS iname, COALESCE(c2.reltuples,0) AS ituples, COALESCE(c2.relpages,0) AS ipages,
      COALESCE(CEIL((c2.reltuples*(datahdr-12))/(bs-20::FLOAT)),0) AS iotta -- very rough approximation, assumes all cols
    FROM (
      SELECT
        ma,bs,schemaname,tablename,
        (datawidth+(hdr+ma-(CASE WHEN hdr%ma=0 THEN ma ELSE hdr%ma END)))::NUMERIC AS datahdr,
        (maxfracsum*(nullhdr+ma-(CASE WHEN nullhdr%ma=0 THEN ma ELSE nullhdr%ma END))) AS nullhdr2
      FROM (
        SELECT
          schemaname, tablename, hdr, ma, bs,
          SUM((1-null_frac)*avg_width) AS datawidth,
          MAX(null_frac) AS maxfracsum,
          hdr+(
            SELECT 1+COUNT(*)/8
            FROM pg_stats s2
            WHERE null_frac<>0 AND s2.schemaname = s.schemaname AND s2.tablename = s.tablename
          ) AS nullhdr
        FROM pg_stats s, (
          SELECT
            (SELECT current_setting('block_size')::NUMERIC) AS bs,
            CASE WHEN SUBSTRING(v,12,3) IN ('8.0','8.1','8.2') THEN 27 ELSE 23 END AS hdr,
            CASE WHEN v ~ 'mingw32' THEN 8 ELSE 4 END AS ma
          FROM (SELECT version() AS v) AS foo
        ) AS constants
        GROUP BY 1,2,3,4,5
      ) AS foo
    ) AS rs
    JOIN pg_class cc ON cc.relname = rs.tablename
    JOIN pg_namespace nn ON cc.relnamespace = nn.oid AND nn.nspname = rs.schemaname AND nn.nspname <> 'information_schema'
    LEFT JOIN pg_index i ON indrelid = cc.oid
    LEFT JOIN pg_class c2 ON c2.oid = i.indexrelid
  ) AS sml
  ORDER BY wastedbytes DESC;

이번 글에서는 docker 관계없이 PostgreSQL에서 oracle_fdw를 설치 및 외부 테이블 생성하여 데이터를 조회해보는 작업까지를 진행하려고 한다. 

설치전 확인 및 고지 사항

  • 오라클 클라이언트 버전 확인 후 설치 필요(필수)

  • oracle fdw github에서 README 확인 필요(오라클 client 호환 버전 관련)

    https://github.com/laurenz/oracle_fdw

  • fdw나 dblink는 온라인 업무에는 권장하지 않음

  • 보편적인 체크 사항들 목록

오라클 클라이언트 다운로드가 필요(zip 파일) - 오라클 계정 필요
오라클 서버와 버전이 맞는 버전을 사용하는 것이 좋음(이슈 관련)
32비트 오라클 서버와 64비트 PostgreSQL 서버는 동작 불가.(동일한 bit의 프로그램 필요)
#SELECT * FROM v$version; 로 oracle 버전 정보 확인

----------Oracle client version 11.2 or better is required.---------- oracle_fdw 2.3.0버전 기준
그 외 호환 버전 정보는 Matrix in support document 207303.1 문서 참조
호환 Matrix에서는 최신 버전이 아닌 oracle 버전의 호환성에 대해 확인해주지 않는다는 점은 감안하여야 한다.
oracle_fdw 2.2.0 버전 기준 oracle client 10.2버전은 지원하지 않는다.

 

  • 오라클 부분 확인 내용
--SID값으로 Service_name값 확인하기, 확인한 Service_name값으로 foreign server 설정값에 넣어주면 된다.
select value from v$parameter where name='<sid값>';
-------------------------
ORCLCDB.localdomain

 

  • PostgreSQL 서버에서 필요한 파일 download 후 extension 설치하기
# Oracle Client Download
http://www.oracle.com/technetwork/topics/linuxx86-64soft-092277.html
 instantclient-basic-linux.x64-11.2.0.4.0.zip
 instantclient-sdk-linux.x64-11.2.0.4.0.zip
 instantclient-sqlplus-linux.x64-11.2.0.4.0.zip

# oracle fdw download
https://github.com/laurenz/oracle_fdw
 oracle_fdw-ORACLE_FDW_2_2_0.zip

#unzip all zip files
unzip instantclient-basic-linux.x64-11.2.0.4.0.zip
unzip instantclient-sdk-linux.x64-11.2.0.4.0.zip
unzip instantclient-sqlplus-linux.x64-11.2.0.4.0.zip
unzip oracle_fdw-ORACLE_FDW_2_2_0.zip

#환경변수 추가 
 #LD_LIBRARY_PATH 변수 끝에 :<오라클 클라이언트 압축 해제 경로> 추가
예) export LD_LIBRARY_PATH=$PGLIB:/home/seandb/instantclient_11_2
 #새로 추가 필요
export ORACLE_HOME=/home/seandb/instantclient_10_2
export TNS_ADMIN=/home/seandb/instantclient_10_2

#환경변수 적용 확인
source ~/.bashrc ~/.bash_profile
cd $ORACLE_HOME;pwd;cd -
cd $TNS_ADMIN;pwd;cd -
echo $LD_LIBRARY_PATH

## 라이브러리 파일 존재 여부 확인
ls -al $ORACLE_HOME/libclntsh*

# 오라클 클라이언트 디렉토리에 있는 so 파일 관련 링크 설정.
cd $ORACLE_HOME
ln -s libclntsh.so.11.1 libclntsh.so

#oracle pwd 빌드 및 설치
cd oracle_fdw-master
make&&make install

#PostgreSQL 재기동
pg_ctl stop
pg_ctl start

#oracle_fdw 익스텐션 설치
-- drop EXTENSION oracle_fdw;
CREATE EXTENSION oracle_fdw;

#외부 테이블 목록 조회
select * from pg_foreign_table;

 

  • 서버 연결 및 확인 방법
--drop server oradb cascade;
--service name으로 외부(foreign) server 등록하기
CREATE SERVER oradb FOREIGN DATA WRAPPER oracle_fdw OPTIONS (dbserver '//192.168.56.222:1521/ORCLCDB.localdomain');

--하단의 명령어는 tnsnames.ora를 생성해준 뒤에 그 정의된 이름을 사용하는 방법이다.
vi tnsnames.ora
TESTDB =
        ( DESCRIPTION =
                ( ADDRESS_LIST =
                        ( ADDRESS = ( PROTOCOL = TCP ) ( HOST = 192.168.56.222 ) ( PORT = 1521 ) )
                )
                ( CONNECT_DATA =
                        ( SID = ORCLCDB )
                )
        )
CREATE SERVER oradb FOREIGN DATA WRAPPER oracle_fdw OPTIONS (dbserver 'TESTDB');

--혹은 하단과 같이 옵션을 전부 명시해주어도 동작한다
CREATE SERVER pdspawn FOREIGN DATA WRAPPER oracle_fdw OPTIONS (dbserver '(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(Host=myhost.com)(Port=1521))(CONNECT_DATA=(SID=FOREIGN_DATABASE)))');

-- 별도 유저 생성 및 권한 부여가 필요한 경우 값들 변경하여 사용
--CREATE USER oracon PASSWORD 'oracon' LOGIN ;
--GRANT usage ON FOREIGN SERVER oradb TO oracon ;
--GRANT usage ON SCHEMA public TO oracon ;

CREATE USER MAPPING FOR experdba SERVER oradb OPTIONS (user 'oracle', password 'orapass');
-- oracle_fdw 익스텐션에서 제공하는 함수로 설정이 정상적으로 되었는지 확인 가능하다.
select oracle_diag('oradb');

--drop foreign table fr_persons;
CREATE FOREIGN TABLE fr_persons(
  PERSON_ID NUMERIC NOT NULL
, FIRST_NAME VARCHAR(50)
, LAST_NAME VARCHAR(50)
) SERVER oradb OPTIONS (SCHEMA 'ORACLE', TABLE 'PERSONS');

select * from fr_persons;

 

  • oracle_fdw 관련 함수 목록
oracle_close_connections();
oracle_diag();
oracle_execute();
oracle_fdw_handler();
oracle_fdw_validator();

 

  • 관련 오브젝트 목록 조회
seandb=> select * from pg_foreign_data_wrapper ;
  oid  |  fdwname   | fdwowner | fdwhandler | fdwvalidator | fdwacl | fdwoptions
-------+------------+----------+------------+--------------+--------+------------
 16495 | dblink_fdw |    16386 |          0 |        16494 |        |
 16601 | oracle_fdw |       10 |      16596 |        16597 |        |
(2 rows)

seandb=> select * from pg_foreign_server
seandb-> ;
  oid  | srvname | srvowner | srvfdw | srvtype | srvversion |                 srvacl
            |                srvoptions
-------+---------+----------+--------+---------+------------+-----------------------------
------------+------------------------------------------
 16602 | oradb   |       10 |  16601 |         |            | {seandba=U/seandba,oracon=
U/seandba} | {dbserver=//192.168.56.222:1521/orclcdb}
(1 row)

seandb=> select * from pg_foreign_table ;
 ftrelid | ftserver |            ftoptions
---------+----------+----------------------------------
   16604 |    16602 | {schema=SYSTEM,table=TEST_TABLE}
   16607 |    16602 | {schema=ORACLE,table=PERSONS}
(2 rows)

 

  • 외부 테이블 생성 후 테이블에 대한 정보 조회방법
select * from information_schema.tables where lower(table_type) like 'foreign';

 table_catalog | table_schema | table_name | table_type | self_referencing_column_name | reference_generation | user_defined_type_catalog | user_defined_type_schema | user_defined_type_name | is_insertable_into
| is_typed | commit_action
---------------+--------------+------------+------------+------------------------------+----------------------+---------------------------+--------------------------+------------------------+--------------------
+----------+---------------
 seandb       | seandba     | fr_persons | FOREIGN    |                              |                      |                           |                          |                        | YES
| NO       |
(1 row)

 

reference list:

https://github.com/laurenz/oracle_fdw/wiki

https://www.postgresql.org/docs/12/sql-createserver.html

 

 

'PostgreSQL' 카테고리의 다른 글

oracle_fdw 내용정리  (0) 2022.02.21
bloat postgresql check query  (0) 2021.07.18
PostgreSQL에 oracle_fdw 설정하기- 1/2  (0) 2021.01.20
PostgreSQL 13(1편 Index size)  (0) 2020.09.27

다른 DBMS에도 존재하지만 PostgreSQL에서 종종 필요한 부분들은 DBLINK로, 다른 종류의 DBMS와 연결을 통해

원하는 정보를 가져오는 것이다.

이번 글에서는 Docker로 Oracle DBMS 컨테이너를 생성, PostgreSQL에서 oracle_fdw를 설치, 외부 테이블을 만들어

조회하는 것을 2개의 글로 나누어 구성해 볼 것이다.

첫번째 글은 Oracle DBMS 12버전을 docker 컨테이너로 올리는 부분이다.

두번째 글에서는 postgreSQL 12버전에서 oracle_fdw 확장 프로그램을 설치하여 Oracle에 있는 테이블을 조회하는 것을 다뤄보겠다.



Docker 환경에서 Oracle 사용하기

  • Migrator나 DBLINK 등의 연결방식의 환경 테스트가 필요한 경우에 유용할듯

  • Migration Test 진행할 때에 개인적으로 사용 가능할듯.

  • oracle docker 이용을 위해서는 최소 30기가 정도의 디스크 공간이 필요하다.

docker image pull을 위한 작업들

  1. Docker Hub에서 login 후 진행해야 한다
  2. https://hub.docker.com/_/oracle-database-enterprise-edition (2020.03)
  3. 접속하여 Proceed to checkout 버튼 클릭 후 정보 입력
  4. 사용하고자 하는 Docker 환경에 터미널 연결
  5. docker login 명령어로 docker hub 아이디/암호 입력
  6. docker pull store/oracle/database-enterprise:12.2.0.1 명령으로 image 다운로드

 

Oracle Docker Container 실행

  1. oracle.env 파일 생성(유저,암호 등 설정파일)

     TZ=Asia/Seoul
     ORACLE_SID=ORCL
     ORACLE_PDB=MYORCL
     ORACLE_PWD=oracle
     ORACLE_CHARACTERSET=UTF8
  1. env 파일 load 하는 방식으로 컨테이너 생성.

    docker run -d --name sean_ora12c --env-file ./oracle.env -p 1521:1521 -it store/oracle/database-enterprise:12.2.0.1 
    ## volume 사용시
    ##docker run -d --name sean_ora12c --env-file ./oracle.env -p 1521:1521 -it -name sean_ora12c -v /root/:/ORCL store/oracle/database-enterprise:12.1.0.1
    ## slim 버전
    ##docker run -d --env-file ./oracle.env -p 1521:1521 -it -name sean_ora12c -v /root/:/ORCL store/oracle/database-enterprise:12.2.0.1-slim
    
    ## 컨테이너 내려갔을때 올리기
    docker start sean_ora12c
    # 별도 작업 필요없음
  1. docker logs -f sean_ora12c 명령어로 진행상황 확인

     The command completed successfully
    
     DONE!
     Remove password info
     Docker DB configuration is complete !
     configDB.sh is done at 297 sec
    
     Done ! The database is ready for use .

 

User 생성 및 권한 설정

  • 도커 환경에서 exec로 컨테이너 접근
$ docker exec -it sean_ora12c bash -c "source /home/oracle/.bashrc; sqlplus sys/Oradoc_db1@ORCLCDB as sysdba"
  • 유저 생성 및 암호 설정, 권한 설정
alter session set "_ORACLE_SCRIPT"=true;

## 유저 oracle, 암호 orapass
create user oracle identified by orapass;

grant connect, resource, dba to oracle;
  • sysdba로 접근 후 DB, SID 확인
docker exec -it sean_ora12c bash -c "source /home/oracle/.bashrc; sqlplus sys/Oradoc_db1@ORCLCDB as sysdba"

SELECT NAME, DB_UNIQUE_NAME FROM v$database;
SELECT instance FROM v$thread;

 

DBeaver Oracle 접속

  1. 필요한 드라이버 다운로드 후 DBeaver에 위치 등록.
  1. 접속 정보 입력 후 접속 테스트(SID = ORCLCDB, 아이디, 암호는 위에서 생성한 대로)

 

https://hub.docker.com/u/dosroad/content/sub-79223df5-6a1f-4c40-a3b2-96d36ff84172

http://1004lucifer.blogspot.com/2019/11/docker-oracle-12c-oracle.html

oracle xe 18c 설치

https://emflant.tistory.com/237

'PostgreSQL' 카테고리의 다른 글

bloat postgresql check query  (0) 2021.07.18
PostgreSQL에 oracle_fdw 설정하기- 2/2  (0) 2021.01.20
PostgreSQL 13(1편 Index size)  (0) 2020.09.27
PostgreSQL Toast에 관한 정리  (0) 2020.09.26

T14S를 구입하고 준비했던 것들을 시작했다.

 

물량이 없는 관계로 물건을 받기까지 충분한 조사 기간이 있었고,(레딧, 레노버 공식 페이지 등)

 

제품을 받자마자 제일 먼저 한 작업은 분해 후 써멀 구리스를 재도포 한 것이었다.

 

그리고 남는 WWAN 슬롯에는 화이트 리스트로 인해 구입가도 비싸고(100불 이상)

 

남는 SN520 SSD가 호환이 되는것을 확인, 2번째 SSD를 장착해서 중요 데이터의 2차 백업용으로 사용중이며

 

지금 나에게 있는 모델은 사진과 같은 M.2 2280 규격이기에 WWAN 포트에 들어가도록 2242 사이즈로 만들었고,

 

2280 M.2 NVME 256GB의 메인 SSD는 미리 아마존에서 구입해놓은 동일 규격의 SN750 1TB 제품으로 교체하였다.

 

이후의 내용은 간단한 진행과정이다.

 

1. 기본 써멀을 그리즐리 써멀이라 불리는 Thermal Grizzly Kryonaut 써멀로 재도포해주었다.

   재미있는 부분은 재도포 직후 벤치마크 결과가 훨씬 안좋게 나왔었다는 점과

   2일쯤 지나자 기본 써멀 기준 5% 가량 성능 개선이 되었다는 점이다. 

 

 

2. 기존 장착되어 있던 SSD는 삼성의 PM981 256GB 모델이었다. 현재는 SN750 모델로 교체되어 있으며, 그램용으로 나온 써멀패드를 장착, 그램과 동일한 재질인 T14S의 마그네슘 하판을 방열판처럼 사용하고 있다. 평소 때 온도는 25도로 센서에서 표기되고 있다. 

다른 NVME SSD와 비교하여 SN750이 소비전력이 조금 많은 편이기 때문에 노트북 배터리 모드로 사용시에 사용시간 차이가 조금 생길 것 같지만, 초기 구매시 미처 고려하지 못했던 부분이라 추후에 SSD를 추가로 구입하거나 할 때 교체할 계획이다.

 

 

 

3-1. 마지막으로 WD SN520 2280모델을 WWAN 포트에 장착하는 일이다. 마땅한 툴이 없어 자와 커터칼로 작업하였다. SSD 특성상 장애가 발생하면 백업본 없이는 데이터 복구가 불가능한 수준이라 2번째 SSD가 유용하게 백업 용도로 사용될 것이다.

 

 

3-2. 의외로 2242 사이즈로 자르는 작업보다는 나사홀을 만들어 주는 작업이 더 오래 걸렸다.

 

 

4. 어쩌다 보니 T14S에 장착된 두개의 SSD가 모두 WD 제품이라 WD dashboard 프로그램을 설치하고 실행해보았다.

메인 SSD인 SN750은 PCIe Gen 3이며 4 lane으로 동작한다. 

WWAN 포트에 장착된 서브 SSD인 SN520은 동일하기 PCIe Gen3이지만, 1 lane으로 동작한다.

이런 차이로 속도에 제한이 걸릴 것 같지만, 데이터 백업용으로는 충분한 성능이 나와준다.

 

내용 정리

써멀 구리스는 도포 직후에는 성능이 안나올 수 있다.

T14S의 하판은 LG 그램과 마찬가지로 마그네슘으로 SSD 방열패드를 이용하여 쿨링이 가능하다.(효과가 좋음)

T14S의 WWAN 포트에는 WD SN520 NVME SSD가 장착이 가능하다(2242 사이즈)

WWAN 포트에 SSD를 장착하는 경우 성능 위주로 사용은 힘들다.(300MB/s까지는 확인)

WWAN 포트에 장착한 SSD로 부팅도 가능하다고는 하지만 시도해보지는 않았음.

'IT 관련' 카테고리의 다른 글

시놀로지 보안 관련 인증서 설정  (0) 2023.07.27
씽크센터 m75q tiny 구입  (0) 2022.02.21
Thinkpad T14s AMD 구입기  (0) 2020.09.26
샤오미 스마트 선풍기  (0) 2018.05.02

 

며칠 전인 9월 24일에 PostgreSQL 13 정식 버전이 릴리즈 되었다.

이번 기회에 개인적으로 공부도 할겸, 공식 문서와 해외 여러 곳에서 다룬 이번 PG13에 대한 글들을 한글로 정리하고자 한다.

참조한 곳들은 이 글들의 가장 아래에 언급해 두었다. 내용이 이해가 가지 않거나, 불명확한 부분이 있다면 그곳을 참고하기 바란다.

PG 13 버전에서 성능과 관련하여 변경된 점들 중, 가장 관심이 가는 부분들은 중복 데이터 관련하여 B-TREE 인덱스 사이즈가 줄어든 것,인덱스에 대한 VACUUM 작업과 REINDEX 작업이 병렬 처리 지원이 된다는 점들이다. 그 외에도 파티션 관련 성능 개선이나 사용되었던 복제 슬롯으로 인한 WAL 파일 늘어남으로 인한 DISK 용량 관리 문제 등이 해결되었다.

이 중 제일 먼저 다룰 부분은 중복 데이터 존재시의 B-TREE 인덱스 크기 변화이며, PG 11, 12 그리고 13 버전에서의 용량 그리고 성능 차이를 다뤄 보겠다.

B-Tree Index 크기 변화

PostgreSQL 12 버전 릴리즈 때에도 multi-column에 생성한 인덱스 관련하여 중복값 관련 인덱스 용량이 30%가량 줄어들었던 것으로 기억하는데, PG 13에서는 어떤 변화가 있는지에 대해 알아보도록 하자.

인덱스 생성에 사용한 구문(300만건)

# CREATE TABLE rel (
#    aid bigint NOT NULL,
#    bid bigint NOT NULL
# );
CREATE TABLE
# ALTER TABLE rel
#    ADD CONSTRAINT rel_pkey PRIMARY KEY (aid, bid);
ALTER TABLE
# CREATE INDEX rel_bid_idx ON rel (bid);
CREATE INDEX
#  INSERT INTO rel (aid, bid)
#     SELECT i, i / 10000
#     FROM generate_series(1, 3000000) AS i;

위의 방식으로 생성한 데이터는 aid의 경우는 1부터 300만까지가 중복없이 존재하고 bid의 경우는 0부터 299까지의 중복되는 값이 대략 10000건씩 존재하게 된다. 이제 각 버전에서 각 인덱스들이 차지하는 용량을 비교해보도록 하자.

버전별로 생성된 인덱스들이 차지하는 디스크 용량

*PostgreSQL 11 *

# select version();
                                                 version
------------------------------------------------------------------------------------------
 PostgreSQL 11.7 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8
(1 row)

# \di+
                            List of relations
  Schema  |    Name     | Type  |  Owner   | Table |  Size  | Description
----------+-------------+-------+----------+-------+--------+-------------
 public | rel_bid_idx | index | postgres | rel   | 281 MB |
 public | rel_pkey    | index | postgres | rel   | 299 MB |
(2 rows)

PostgreSQL 12

# select version();
                                                 version

------------------------------------------------------------------------------------------
---------------
 PostgreSQL 12.3 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8
.5-39), 64-bit
(1 row)

# \di+
                           List of relations
 Schema  |    Name     | Type  |  Owner  | Table |  Size  | Description
---------+-------------+-------+---------+-------+--------+-------------
 public | rel_bid_idx | index | postgres | rel   | 152 MB |
 public | rel_pkey    | index | postgres | rel   | 134 MB |
(2 rows)

PostgreSQL 13

# select version();
                                                 version
------------------------------------------------------------------------------------------
 PostgreSQL 13.0 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8
(1 row)

# \di+
                                  List of relations
 Schema  |    Name     | Type  |  Owner  | Table | Persistence |  Size  | Description
---------+-------------+-------+---------+-------+-------------+--------+-------------
 public | rel_bid_idx | index | postgres | rel   | permanent   | 56 MB  |
 public | rel_pkey    | index | postgres | rel   | permanent   | 179 MB |
(2 rows)
  • 중복값 관련 인덱스 용량 변화량
PG version rel_bid_idx rel_pkey
11.7 281 MB 299 MB
12.3 152 MB(54%) 134 MB(44%)
13.0 56 MB(20%) 179 MB(59%)

용량의 변화가 인덱스를 사용한 쿼리 플랜에 어떤 영향을 미치는지 확인해보기 위해, 하단의 간단한 쿼리를 수행시켜, 수행시간을 비교해보았다.

select min(bid) from rel where aid between 10000 and 150000;

PostgreSQL 11

                                QUERY PLAN
---------------------------------------------------------------------------
 Result (actual rows=1 loops=1)
   Buffers: shared hit=174
   InitPlan 1 (returns $0)
     ->  Limit (actual rows=1 loops=1)
           Buffers: shared hit=174
           ->  Index Scan using rel_bid_idx on rel (actual rows=1 loops=1)
                 Index Cond: (bid IS NOT NULL)
                 Filter: ((aid >= 10000) AND (aid <= 150000))
                 Rows Removed by Filter: 9999
                 Buffers: shared hit=174

PostgreSQL 12

                                QUERY PLAN
---------------------------------------------------------------------------
 Result (actual rows=1 loops=1)
   Buffers: shared hit=85
   InitPlan 1 (returns $0)
     ->  Limit (actual rows=1 loops=1)
           Buffers: shared hit=85
           ->  Index Scan using rel_bid_idx on rel (actual rows=1 loops=1)
                 Index Cond: (bid IS NOT NULL)
                 Filter: ((aid >= 10000) AND (aid <= 150000))
                 Rows Removed by Filter: 9999
                 Buffers: shared hit=85

PostgreSQL 13

                                QUERY PLAN
---------------------------------------------------------------------------
 Result (actual rows=1 loops=1)
   Buffers: shared hit=67
   InitPlan 1 (returns $0)
     ->  Limit (actual rows=1 loops=1)
           Buffers: shared hit=67
           ->  Index Scan using rel_bid_idx on rel (actual rows=1 loops=1)
                 Index Cond: (bid IS NOT NULL)
                 Filter: ((aid >= 10000) AND (aid <= 150000))
                 Rows Removed by Filter: 9999
                 Buffers: shared hit=67
 Planning:
   Buffers: shared hit=8

실제로 인덱스 블록의 READ 수가 줄어들었음을 확인할 수 있으며, 이는 결국 성능 개선으로 연결될 것이다. 테이블의 사이즈가 더 커지고, 사용하는 인덱스가 많아질 수록, 이러한 변화는 DB 레벨로 보았을 때 결코 적지 않은 차이로 이어질 것이다.

한가지 염두에 두어야 할 점이 있다면, PostgreSQL 12버전 릴리즈 때도 마찬가지였지만 기존 버전을 PG_UPGRADE를 이용하여 버전을 변경한 경우, 인덱스 용량 개선과 그로 인한 성능 개선의 혜택을 보고 싶다면, REINDEX 작업이 필요하다. pg_dump&restore 방식으로 작업한다면 이러한 문제는 없겠지만, 별도의 용량과 시간이 필요한 것은 마찬가지이므로, PostgreSQL 운영 환경의 메이저 버전 업그레이드를 생각하고 있다면, PG_UPGRADE 후에 REINDEX 작업이 필요하다는 점을 염두에 두도록 하자.

 

관련되어 PG13부터 추가된 공식 문서에는 어떤 방식으로 중복값 제거가 도입되었고, 어떤 경우에 중복값 제거의 사용이 안되는지에 대해서 언급하고 있다.

https://www.postgresql.org/docs/13/btree-implementation.html

'PostgreSQL' 카테고리의 다른 글

bloat postgresql check query  (0) 2021.07.18
PostgreSQL에 oracle_fdw 설정하기- 2/2  (0) 2021.01.20
PostgreSQL에 oracle_fdw 설정하기- 1/2  (0) 2021.01.20
PostgreSQL Toast에 관한 정리  (0) 2020.09.26

해당 글은 PG 11 기준으로 작성되었습니다.

Toast(The Oversized-Attribute Storage Technique)

정의: Toast는 크기가 고정되지 않는 타입의 Column 에 적용되는 기술로, 보다 큰 column 사이즈를 지원하기 위해 값을 압축/분할하여 별도의 pg_toast에 각각의 row로 담아 관리하는 기술이다.

fixed page size (commonly 8 kB) 보다 큰 경우에 적용된다.

- toast 관련하여 4가지 모드가 있으며, 모드들은 압축 유/무 분할 유/무 에 관련된 내용들이 있다.

- PostgreSQL 11버전 기준으로 toast 관련된 table space를 별도로 지정하는 기능은 없다.
(오라클에는 lob column을 별도의 테이블 스페이스로 지정 가능한 것과 대비된다.)

- 테이블 스페이스 사용하고 text 데이터를 생성하여 toast 테이블 사용하였을 시에 해당 테이블 스페이스에 공간이 늘어나는 것을 확인하였다.

toast table 사용되게 생성 및 확인 관련 쿼리

promdb=# CREATE table t1_toast(message text);
 ##### 테이블 toast 생성#####

 promdb=# INSERT INTO t1_toast
 SELECT (SELECT
    string_agg(chr(floor(random() * 26)::int + 65), '')
     FROM generate_series(1,10000))
 FROM generate_series(1,10);
 ##### 테이블 toast에 row 생성#####

 promdb=# SELECT reltoastrelid::regclass
    FROM pg_class
WHERE relname = 't1_toast';
   reltoastrelid
 -------------------------
 pg_toast.pg_toast_41120
 ##### 테이블 toast의 message row을 압축/분할해서 담고 있는 테이블 명 조회 #####

 promdb-#  SELECT pg pg_toast.pg_toast_41120;
 ##### 압축/분할되어 있는 테이블 내용확인 #####

 

특정 column toast 모드 변경하기(alter table set storage)

alter table t1_toast alter column column_name set storage EXTENDED;

 

량순으로 table 정렬해서 top 20개 보기

SELECT nspname || '.' || relname AS "relation",
    pg_size_pretty(pg_relation_size(C.oid)) AS "size"
  FROM pg_class C
  LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
  WHERE nspname NOT IN ('pg_catalog', 'information_schema')
  ORDER BY pg_relation_size(C.oid) DESC
  LIMIT 20;

 

해당하는 테이블에 연결된 toast 테이블 이름 찾기

select relname from pg_class where oid = (select  reltoastrelid from pg_class where relname='<t1_toast>');

 

 

'PostgreSQL' 카테고리의 다른 글

bloat postgresql check query  (0) 2021.07.18
PostgreSQL에 oracle_fdw 설정하기- 2/2  (0) 2021.01.20
PostgreSQL에 oracle_fdw 설정하기- 1/2  (0) 2021.01.20
PostgreSQL 13(1편 Index size)  (0) 2020.09.27

+ Recent posts