Tagged: pgsql

Better VACCUM FULL For PostgreSQL 9.0

원문:https://wiki.postgresql.org/wiki/What’s_new_in_PostgreSQL_9.0#Better_VACUUM_FULL

지금까지 VACUUM FULL 은 매우 느렸다. 이 구문(Statement)는 테이블로부터 빈공간을 확보하고 그것의 크기(Size)를 줄였지만 VACUUM 은 만족할만큼 빠르게 동작하지 않았다.

이것이 느린 이유는 동작 방법에 문제가 있었기 때문이다. 레코드를 그들의 소스블럭으로부터 테이블에 시작점에 가까운 블럭으로 하나하나씩 읽어서 옮겼었다. 그리고 테이블에 끝이 빈공간이면 그 부분을 지웠다.

전략적으로 이러한 방법은 매우 비효율적(Inefficient) 이다. 레코드를 하나하나씩 옮기는 것은 랜덤 I/O를 발생시킨다. 게다가, 인덱스(Index)를 재구성하는 동안에 그것을 유지하고, 더 많은 비용이 들어가는, 인덱스는 파편화된다. 이럴바에는 VACUUM FULL이 다 끝나고 나서 재인덱스(reindex)를 하는 것이 낫다.

Version 9.0 에서 VACUUM FULL은 테이블과 동일한 또 하나의 테이블을 만들고 거거에 모든 레코드를 순차적이게 복사한다. 모든 레코드가 복사되고 나면, 인덱스를 재생성하고 예전 테이블은 삭제되고 새로운 테이블로 대체된다.

이것은 VACUUM 을 보다 빠르게 한다. 하지만 VACUUM FULL은 동작하는 동안에 AccessExclusiveLock 을 필요로 한다. 이전 방법과 비교했을때 이 방법의 결점은 VACUUM FULL을 했을 경우 새로운 버전의 테이블을 만들기 위해서 디스크에 테이블 크기의 2배의 용량을 사용할 수 있다는 것이다.

이제, 두가지 방법에 대해서 실시간으로 비교를 해보자. 먼저 아래와 같은 방법으로 테스트 데이터를 준비 했다.

8.4 버전에서는.

다 합해 대충 9초 정도 걸렸다.

9.0 버전에서는.

아직 이것은 제품에서(아마 서비스중에라는 뜻인듯..) VACUUM FULL 이 좋은 아이디어라는 뜻은 아니다. 만약 이것이 필요하다면, 아마도 VACUUM 정책이 올바르지 않기 때문일 것이다. (응?)

PostgreSQL 과 문자셋

PostgreSQL 도 문자셋에 관해서 많은 옵션들을 제공한다. 그런데, 대부분은 이에 대해서 잘 모르는 듯해서 여기서 정리해 본다.

PostgreSQL 에서 문자셋 지정을 처음 하는 부분은 바로 설치를 마친후에 initdb 명령어를 사용하면서 부터다 대충 다음과 같이 사용한다.

문제는 저러한 문제셋 설정이 과연 향후 PostgreSQL 을 사용하는데 있어 어떤 영향을 주는가 하는 것이다. 먼저 PostgreSQL 은 ISO C 와 POSIX 등의 언어표현에 관해 지원 한다.

Locale

보통 initdb –locale=ko_KR.UTF-8 로 사용되어지는 것으로 운영체제에 종속적이다. 운영체제에서 지원하는 locale 만 사용할 수 있는데, 리눅스의 경우에는 ‘locale -a’ 명령어로 확인 가능하다.

이는 운영체제의 사용자에게 보여주는 메시지 문자를 지정한다. 만일 영어로 운영체제를 사용하고 싶다면 바로 이 locale 를 변경하면 된다. 그런데, locale 의 설정은 ‘ko_KR.UTF-8’ 처럼 나오는데 이는 language_territory.codeset 형태이다.

language 는 인간의 사용하는 언어이고 territory 는 ‘한 국가가 다스리는 영토, 지역’을 뜻한다. 예를들어서 fr_CA 도 있는데 이는 캐나다에서 사용하는 프랑스어라는 뜻이 된다. codeset 은 이러한 언어를 컴퓨터 언어로 표현하는 문자 셋이다.

이러한 형태가 나온 이유는 한 국가(영토, 지역)에서 두가지 이상의 언어를 사용할 경우를 대비한 것으로 풀이된다.

LC_COLLATE

이는 매우 중요한 것으로 다음과 같은 것에 영향을 미친다.

  1. 대소문자를 구분하는 기능.
  2. 문자열 정렬
  3. ‘like’ 문에서 인덱스를 사용여부 결정

이는 데이터베이스를 생성할때에도 지정할 수가 있는데, 지정하는 방법은 locale 과 같이 language_territory.codeset 형식이지만 codeset 은 생략하는 경우가 있다. 다음과 같은 명령어로 확인 가능하다.

문제는 이 LC_COLLATE 는 initdb 시에 한번 결정이 되면 바꿀 수 없고 하지만, Template 을 1번이 아닌 0번으로 할 경우에는 가능하다. Template1 은 initdb 때 생성되는 일종의 Master  DB라 보면되고 모든 데이터베이스는 이 Template1 을 기반으로 생성되어진다.

LC_CTYPE

이는 문자의 범주를 정하는 것으로 각 언어마다 가지고 있는 고유한 특성을 타나내기도 한다. 예를들면 단어가 무엇인지, 대문자와 소문자,one byte 문자인지 multi byte 문자인지에 대한 정의등에 대한 것이다. 이는 initdb 실에 결정되면 바꿀 수 없다.

대부분 Locale 을 따라 지정하는게 낫다.

LC_MESSAGE  

이는 접속한 클라이언트에게 어떤 언어로 보여줄지를 결정한다.

LC_MONETARY 

이는 접속한 클라이언트에게 어떤 화폐단위로 보여줄 것인지를 결정한다.

LC_NUMERIC

이는 접속한 클라이언트에게 어떤 숫자단위로 보여줄 것인지를 결정한다.

LC_TIME

이는 접속한 클라이언트에게 날짜와 시간에 대한 포맷을 결정한다.