

# lo 모듈을 사용하여 대형 객체 관리
<a name="PostgreSQL_large_objects_lo_extension"></a>

lo 모듈(확장)은 JDBC 또는 ODBC 드라이버를 통해 PostgreSQL 데이터베이스로 작업하는 데이터베이스 사용자 및 개발자를 위한 것입니다. JDBC와 ODBC는 모두 참조가 변경될 때 데이터베이스에서 대형 객체의 삭제를 처리할 것으로 예상합니다. 그러나 PostgreSQL은 이런 식으로 작동하지 않습니다. PostgreSQL 참조가 변경될 때 객체를 삭제해야 한다고 가정하지 않습니다. 따라서 객체는 참조되지 않고 디스크에 남아 있게 됩니다. lo 확장에는 필요한 경우 객체를 삭제하기 위해 참조 변경 사항을 트리거하는 데 사용하는 함수가 포함되어 있습니다.

**작은 정보**  
데이터베이스가 lo 확장의 이점을 누릴 수 있는지 확인하려면 `vacuumlo` 유틸리티를 사용하여 분리되어 있는 대형 객체가 있는지 확인합니다. 작업을 수행하지 않고 분리되어 있는 대형 객체 수를 확인하려면 `-n` 옵션(no-op)과 함께 유틸리티를 실행하면 됩니다. 자세한 방법은 다음 [vacuumlo utility](#vacuumlo-utility) 섹션을 참조하세요.

lo 모듈은 Aurora PostgreSQL 13.7, 12.11, 11.16, 10.21 이상 마이너 버전에서 사용할 수 있습니다.

모듈(확장)을 설치하려면 `rds_superuser` 권한이 필요합니다. lo 확장을 설치하면 데이터베이스에 다음이 추가됩니다.
+ `lo` - 바이너리 대형 객체(BLOB) 및 기타 대형 객체에 사용할 수 있는 대형 객체(lo) 데이터 유형입니다. `lo` 데이터 유형은 `oid` 데이터 유형의 영역에 있습니다. 바꿔 말하면 선택적 제약 조건이 포함된 객체 식별자입니다. 자세한 내용은 PostgreSQL 설명서의 [객체 식별자](https://www.postgresql.org/docs/14/datatype-oid.html)를 참조하세요. 간단히 말해, `lo` 데이터 유형을 사용하여 대형 객체 참조가 들어 있는 데이터베이스 열을 다른 객체 식별자(OID)와 구별할 수 있습니다.
+ `lo_manage` - 대형 객체 참조가 포함된 테이블 열의 트리거에 사용할 수 있는 함수입니다. 대형 객체를 참조하는 값을 삭제하거나 수정할 때마다 트리거는 객체(`lo_unlink`)를 참조에서 분리합니다. 열이 대형 객체에 대한 유일한 데이터베이스 참조인 경우에만 열에 트리거를 사용합니다.

대형 객체 모듈에 대한 자세한 내용은 PostgreSQL 설명서의 [lo](https://www.postgresql.org/docs/current/lo.html)를 참조하세요.

## lo 확장 설치
<a name="PostgreSQL_large_objects_lo_extension.install"></a>

lo 확장을 설치하려면 `rds_superuser` 권한이 필요합니다.

**lo 확장 설치**

1. `psql`을 사용하여 Aurora PostgreSQL DB 클러스터의 프라이머리 DB 인스턴스에 연결합니다.

   ```
   psql --host=your-cluster-instance-1.666666666666.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password
   ```

   메시지가 표시되면 암호를 입력합니다. `psql` 클라이언트는 기본 관리 연결 데이터베이스인 `postgres=>`를 연결하고 프롬프트로 표시합니다.

1. 다음과 같이 확장을 설치합니다.

   ```
   postgres=> CREATE EXTENSION lo;
   CREATE EXTENSION
   ```

이제 `lo` 데이터 유형을 사용하여 테이블의 열을 정의할 수 있습니다. 예를 들어, 래스터 이미지 데이터가 들어 있는 테이블(`images`)을 생성할 수 있습니다. 테이블을 생성하는 다음 예와 같이 열 `raster`에 `lo` 데이터 유형을 사용할 수 있습니다.

```
postgres=> CREATE TABLE images (image_name text, raster lo);
```

## lo\$1manage 트리거 함수를 사용하여 객체 삭제
<a name="PostgreSQL_large_objects_lo_extension.using"></a>

`lo`의 트리거 또는 다른 대형 객체 열에서 `lo_manage` 함수를 사용하여 `lo`가 업데이트되거나 삭제될 때 분리된 객체를 지우거나 발생하지 않도록 방지할 수 있습니다.

**대형 객체를 참조하는 열에 트리거 설정**
+ 다음 중 하나를 수행하세요.
  + 인수의 열 이름을 사용하여 대형 객체에 대한 고유한 참조를 포함하도록 각 열에 BEFORE UPDATE OR DELETE 트리거를 생성합니다.

    ```
    postgres=> CREATE TRIGGER t_raster BEFORE UPDATE OR DELETE ON images
        FOR EACH ROW EXECUTE FUNCTION lo_manage(raster);
    ```
  + 열이 업데이트되는 경우에만 트리거를 적용합니다.

    ```
    postgres=> CREATE TRIGGER t_raster BEFORE UPDATE OF images
        FOR EACH ROW EXECUTE FUNCTION lo_manage(raster);
    ```

`lo_manage` 트리거 함수는 트리거를 정의하는 방법에 따라 열 데이터를 삽입하거나 삭제하는 맥락에서만 작동합니다. 데이터베이스에서 `DROP` 또는 `TRUNCATE` 작업을 수행할 때는 영향을 미치지 않습니다. 즉, 삭제하기 전에 테이블에서 객체 열을 삭제하여 분리된 객체가 생성되지 않도록 해야 합니다.

예를 들어, `images` 테이블을 포함하는 데이터베이스를 삭제한다고 가정해 봅니다. 다음과 같이 열을 삭제합니다.

```
postgres=> DELETE FROM images COLUMN raster
```

해당 열에 삭제를 처리하는 `lo_manage` 함수가 정의되어 있다는 가정하에 이제 테이블을 안전하게 삭제할 수 있습니다.

## `vacuumlo`를 사용하여 고립된 대형 객체 제거
<a name="PostgreSQL_large_objects_lo_extension.vacuumlo-utility"></a>

 `vacuumlo` 유틸리티는 데이터베이스에서 고립된 대형 객체를 식별하고 제거할 수 있습니다. 이 유틸리티는 PostgreSQL 9.1.24부터 지원됩니다. 데이터베이스 사용자가 대형 객체로 자주 작업하는 경우 가끔 `vacuumlo`를 실행하여 분리되어 있는 대형 객체를 정리하는 것이 좋습니다.

lo 확장을 설치하기 전에 `vacuumlo`를 사용하여 Aurora PostgreSQL DB 클러스터의 이점을 얻을 수 있는지를 평가할 수 있습니다. 이렇게 하려면 다음과 같이 `-n` 옵션(no-op)과 함께 `vacuumlo`를 실행하여 제거할 항목을 표시합니다.

```
$ vacuumlo -v -n -h your-cluster-instance-1.666666666666.aws-region.rds.amazonaws.com -p 5433 -U postgres docs-lab-spatial-db
Password:*****
Connected to database "docs-lab-spatial-db"
Test run: no large objects will be removed!
Would remove 0 large objects from database "docs-lab-spatial-db".
```

출력에서 알 수 있듯이 분리된 대형 객체는 이 특정 데이터베이스에서는 문제가 되지 않습니다.

유틸리티에 대한 자세한 내용은 PostgreSQL 설명서의 [https://www.postgresql.org/docs/current/vacuumlo.html](https://www.postgresql.org/docs/current/vacuumlo.html) 섹션을 참조하세요.

## `vacuumlo` 작동 방식 이해
<a name="PostgreSQL_large_objects_lo_extension.vacuumlo-remove"></a>

 `vacuumlo` 명령은 사용자 테이블에 영향을 미치거나 충돌하지 않고 PostgreSQL 데이터베이스에서 고립된 대형 객체(LO)를 제거합니다.

명령은 다음과 같이 작동합니다.

1. `vacuumlo`는 데이터베이스에 있는 대형 객체의 모든 객체 ID(OID)가 포함된 임시 테이블을 만드는 것으로 시작합니다.

1. 그런 다음 `vacuumlo`는 데이터 유형 `oid` 또는 `lo`를 사용하는 데이터베이스의 모든 열을 스캔합니다. `vacuumlo`가 이러한 열에서 일치하는 OID를 찾으면 임시 테이블에서 OID를 제거합니다. `vacuumlo`는 이러한 유형을 기반으로 하는 도메인이 아니라 이름이 `oid` 또는 `lo`인 열만 검사합니다.

1. 임시 테이블의 나머지 항목은 고립된 LO를 나타내며, `vacuumlo`가 안전하게 제거합니다.

## `vacuumlo` 성능 개선
<a name="PostgreSQL_large_objects_lo_extension.vacuumlo-improve"></a>

 `-l` 옵션을 사용하여 배치 크기를 늘려 `vacuumlo`의 성능을 잠재적으로 개선할 수 있습니다. 이렇게 하면 `vacuumlo`가 한 번에 더 많은 LO를 처리할 수 있습니다.

 시스템에 충분한 메모리가 있고 메모리에 임시 테이블을 완전히 수용할 수 있는 경우 데이터베이스 수준에서 `temp_buffers` 설정을 늘리면 성능이 향상될 수 있습니다. 이렇게 하면 테이블이 메모리에 완전히 상주할 수 있으므로 전체 성능이 향상될 수 있습니다.

다음 쿼리는 임시 테이블의 크기를 추정합니다.

```
SELECT
    pg_size_pretty(SUM(pg_column_size(oid))) estimated_lo_temp_table_size
FROM
    pg_largeobject_metadata;
```

## 대형 객체에 대한 고려 사항
<a name="PostgreSQL_large_objects_lo_extension.vacuumlo-consider"></a>

다음은 대형 객체로 작업할 때 유의해야 할 몇 가지 중요한 고려 사항입니다.
+ 현재 고립된 LO를 제거하는 다른 방법이 없기 때문에 `Vacuumlo`가 유일한 솔루션입니다.
+ pglogical, 네이티브 논리적 복제, 복제 기술을 사용하는 AWS DMS와 같은 도구는 대형 객체 복제를 지원하지 않습니다.
+ 데이터베이스 스키마를 설계할 때는 가능하면 대형 객체를 사용하지 말고 `bytea`와 같은 대체 데이터 유형을 사용하는 것이 좋습니다.
+ 고립된 LO 관련 문제를 방지하려면 최소 매주 정기적으로 `vacuumlo`를 실행합니다.
+ 대형 객체를 저장하는 테이블에서 `lo_manage` 함수와 함께 트리거를 사용하면 고립된 LO가 만들어지는 것을 방지할 수 있습니다.