

# Aurora DSQL 및 PostgreSQL
<a name="working-with"></a>

Aurora DSQL은 트랜잭션 워크로드용으로 설계된 PostgreSQL 호환 분산 관계형 데이터베이스입니다. Aurora DSQL은 구문 파서, 플래너, 옵티마이저 및 유형 시스템과 같은 핵심 PostgreSQL 구성 요소를 사용합니다.

Aurora DSQL 설계는 지원되는 모든 PostgreSQL 구문이 호환되는 동작을 제공하고 동일한 쿼리 결과를 산출하도록 보장합니다. 예를 들어 Aurora DSQL은 PostgreSQL과 동일한 유형 변환, 산술 연산, 수치 정밀도 및 규모를 제공합니다. 모든 편차가 문서화됩니다.

또한 Aurora DSQL에는 낙관적 동시성 제어 및 분산 스키마 관리와 같은 고급 기능이 도입되었습니다. 이러한 기능을 사용하면 현대적 클라우드 네이티브 분산 애플리케이션의 성능과 확장성을 활용하면서 친숙한 PostgreSQL 도구를 사용할 수 있습니다.

## PostgreSQL 호환성 하이라이트
<a name="dsql-pg-overview-compat"></a>

Aurora DSQL은 현재 PostgreSQL 버전 16을 기반으로 합니다. 주요 내용은 다음과 같습니다.

**와이어 프로토콜**  
Aurora DSQL은 표준 PostgreSQL v3 와이어 프로토콜을 사용합니다. 이를 통해 표준 PostgreSQL 클라이언트, 드라이버 및 도구와 통합할 수 있습니다. 예를 들어 Aurora DSQL은 `psql`, `pgjdbc` 및 `psycopg`와 호환됩니다.

**DDL 구문**  
Aurora DSQL은 트랜잭션 워크로드에 일반적으로 사용되는 다양한 표준 PostgreSQL 표현식 및 함수를 지원합니다. 지원되는 SQL 표현식은 다음을 포함하여 PostgreSQL과 동일한 결과를 산출합니다.  
+ Null 처리
+ 정렬 순서 동작
+ 숫자 연산에 대한 규모 및 정밀도
+ 문자열 작업의 동등성
자세한 내용은 [Aurora DSQL의 SQL 기능 호환성](working-with-postgresql-compatibility.md) 섹션을 참조하세요.

**트랜잭션 관리**  
Aurora DSQL은 ACID 트랜잭션 및 PostgreSQL Repeatable Read와 동등한 격리 수준과 같은 PostgreSQL의 기본 특성을 보존합니다. 자세한 내용은 [Aurora DSQL의 동시성 제어](working-with-concurrency-control.md) 섹션을 참조하세요.

## 분산 아키텍처의 이점
<a name="dsql-pg-overview-arch"></a>

Aurora DSQL의 분산된 공유 없음 설계는 기존 단일 노드 데이터베이스보다 뛰어난 성능과 확장성 이점을 제공합니다. 주요 기능은 다음과 같습니다.

**낙관적 동시성 제어(OCC)**  
Aurora DSQL은 낙관적 동시성 제어 모델을 사용합니다. 이 비잠금 접근 방식은 트랜잭션이 서로 차단하는 것을 방지하고 교착 상태를 제거하며 처리량이 많은 병렬 실행을 활성화합니다. 이러한 기능 덕분에 Aurora DSQL은 대규모로 일관된 성능이 필요한 애플리케이션에 특히 유용합니다. 더 많은 예시는 [Aurora DSQL의 동시성 제어](working-with-concurrency-control.md) 섹션을 참조하세요.

**비동기식 DDL 작업**  
Aurora DSQL은 DDL 작업을 비동기적으로 실행하므로 스키마 변경 중에 중단 없는 읽기 및 쓰기가 가능합니다. 분산 아키텍처를 통해 Aurora DSQL은 다음 작업을 수행할 수 있습니다.  
+ DDL 작업을 백그라운드 작업으로 실행하여 중단을 최소화합니다.
+ 카탈로그 변경 사항을 강력히 일관된 분산 트랜잭션으로 조정합니다. 이렇게 하면 장애 또는 동시 작업 중에도 모든 노드에서 원자성 가시성을 보장할 수 있습니다.
+ 분리된 컴퓨팅 및 스토리지 계층을 사용하여 여러 가용 영역에서 완전 분산된 리더리스 방식으로 작업합니다.
PostgreSQL에서 EXPLAIN 명령을 사용하는 방법에 대한 자세한 내용은 [Aurora DSQL의 DDL 및 분산 트랜잭션](working-with-ddl.md) 섹션을 참조하세요.

# Aurora DSQL의 SQL 기능 호환성
<a name="working-with-postgresql-compatibility"></a>

이어지는 섹션에서는 PostgreSQL 데이터 유형 및 SQL 명령에 대한 Aurora DSQL 지원에 대해 알아봅니다.

**Topics**
+ [Aurora DSQL에서 지원되는 데이터 유형](working-with-postgresql-compatibility-supported-data-types.md)
+ [Aurora DSQL에 지원되는 SQL](working-with-postgresql-compatibility-supported-sql-features.md)
+ [Aurora DSQL에서 지원되는 SQL 명령 하위 집합](working-with-postgresql-compatibility-supported-sql-subsets.md)
+ [PostgreSQL에서 Aurora DSQL로 마이그레이션](working-with-postgresql-compatibility-migration-guide.md)

# Aurora DSQL에서 지원되는 데이터 유형
<a name="working-with-postgresql-compatibility-supported-data-types"></a>

Aurora DSQL은 일반적인 PostgreSQL 유형의 하위 집합을 지원합니다.

**Topics**
+ [숫자 데이터 유형](#numeric-data-types)
+ [문자 데이터 유형](#character-data-types)
+ [날짜 및 시간 데이터 유형](#date-time-data-types)
+ [기타 데이터 유형](#miscellaneous-data-types)
+ [쿼리 런타임 데이터 유형](#working-with-postgresql-compatibility-query-runtime)

## 숫자 데이터 유형
<a name="numeric-data-types"></a>

Aurora DSQL은 다음 PostgreSQL 숫자 데이터 유형을 지원합니다.


| 이름 | 에일리어스 | 범위 및 정밀도 | 스토리지 크기 | 인덱스 지원 | 
| --- | --- | --- | --- | --- | 
| smallint | int2 | 2 bytes | 2 bytes | 예 | 
|  `integer`  |  `int`, `int4`  |  4 bytes  |  4비트  | 예 | 
|  `bigint`  |  `int8`  |  -9,223,372,036,854,775,808\$1\$19,223,372,036,854,775,807  |  8 bytes  | 예 | 
|  `real`  |  `float4`  |  소수 자릿수 6까지의 정밀도  |  4비트  | 예 | 
|  `double precision`  |  `float8`  |  소수 자릿수 15까지의 정밀도  |  8 bytes  | 예 | 
|  `numeric` [ `(`*p*, *s*`)` ]  |  `decimal` [ `(`*p*, *s*`)` ] `dec`[ `(`*p*,*s*`)`]  |  정밀도를 선택할 수 있는 정확한 숫자. 최대 정밀도는 38이며 최대 범위는 37이고1 기본값은 `numeric (18,6)`입니다.  |  정밀도 숫자당 8바이트 \$1 2바이트. 최대 크기는 27바이트입니다.  | 예 | 

1 - `CREATE TABLE` 또는 `ALTER TABLE ADD COLUMN`을 실행할 때 크기를 명시적으로 지정하지 않으면 Aurora DSQL이 기본값을 적용합니다. `INSERT` 또는 `UPDATE` 문을 실행할 때 Aurora DSQL은 제한을 적용합니다.

## 문자 데이터 유형
<a name="character-data-types"></a>

Aurora DSQL은 다음 PostgreSQL 문자 데이터 유형을 지원합니다.


| 이름 | 에일리어스 | 설명 | Aurora DSQL 제한 | 스토리지 크기 | 인덱스 지원 | 
| --- | --- | --- | --- | --- | --- | 
|  `character` [ `(`*n*`)` ]  |  `char` [ `(`*n*`)` ]  |  고정 길이 문자열  |  4,096B1   |  최대 4,100바이트까지 가변  | 예 | 
|  `character varying` [ `(`*n*`)` ]  |  `varchar` [ `(`*n*`)` ]  |  가변 길이 문자열  |  65,535B1   |  최대 65,539바이트까지 가변  | 예 | 
|  `bpchar` [ `(`*n*`)` ]  |    |  고정 길이인 경우 `char`의 별칭입니다. 가변 길이인 경우 이는 후행 공백이 의미상 유의하지 않은 `varchar`의 별칭입니다.  |  4,096B1   |  최대 4,100바이트까지 가변  | 예 | 
|  `text`  |    |  가변 길이 문자열  |  1MiB1   |  최대 1MiB까지 가변  | 예 | 

1 - `CREATE TABLE` 또는 `ALTER TABLE ADD COLUMN`을 실행할 때 크기를 명시적으로 지정하지 않으면 Aurora DSQL이 기본값을 적용합니다. `INSERT` 또는 `UPDATE` 문을 실행할 때 Aurora DSQL은 제한을 적용합니다.

## 날짜 및 시간 데이터 유형
<a name="date-time-data-types"></a>

Aurora DSQL은 다음 PostgreSQL 날짜 및 시간 데이터 유형을 지원합니다.


| 이름 | 에일리어스 | 설명 | Range | 해결 방법 | 스토리지 크기 | 인덱스 지원 | 
| --- | --- | --- | --- | --- | --- | --- | 
|  `date`  |    |  날짜(년, 월, 일)  |  4713 BC\$15874897 AD  | 1일 |  4비트  | 예 | 
|  `time` [ `(`*p*`)` ] [ `without time zone` ]  |  `timestamp`  |  시간대가 없는 시간  | 0\$11 | 1마이크로초 |  8 bytes  | 예 | 
|  `time` [ `(`*p*`)` ] `with time zone`  |  `timetz`  |  시간대를 포함한 시간  |  00:00:00\$11,559\$124:00:00 –1,559  | 1마이크로초 |  12바이트  | 아니요 | 
|  `timestamp` [ `(`*p*`)` ] [ `without time zone` ]  |    |  시간대가 없는 날짜 및 시간  | 4713 BC\$1294276 AD | 1마이크로초 |  8 bytes  | 예 | 
|  `timestamp` [ `(`*p*`)` ] `with time zone`  |  `timestamptz`  |  시간대를 포함한 날짜 및 시간  | 4713 BC\$1294276 AD | 1마이크로초 |  8 bytes  | 예 | 
|  `interval` [ `fields` ] [ `(`*p*`)` ]  |    |  시간 범위  | -178,000,000년\$1178,000,000년 | 1마이크로초 |  16바이트  | 아니요 | 

## 기타 데이터 유형
<a name="miscellaneous-data-types"></a>

Aurora DSQL은 다음과 같은 기타 PostgreSQL 데이터 유형을 지원합니다.


| 이름 | 에일리어스 | 설명 | Aurora DSQL 제한 | 스토리지 크기 | 인덱스 지원 | 
| --- | --- | --- | --- | --- | --- | 
|  `boolean`  |  `bool`  |  논리적 부울(true/false)  |    |  1바이트  | 예 | 
|  `bytea`  |    |  바이너리 데이터('바이트 배열')  |  1MiB1   |  최대 1MiB까지 가변  | 아니요 | 
|  `UUID`  |    |  범용 고유 식별자  |    |  16바이트  | 예 | 

1 - `CREATE TABLE` 또는 `ALTER TABLE ADD COLUMN`을 실행할 때 크기를 명시적으로 지정하지 않으면 Aurora DSQL이 기본값을 적용합니다. `INSERT` 또는 `UPDATE` 문을 실행할 때 Aurora DSQL은 제한을 적용합니다.

## 쿼리 런타임 데이터 유형
<a name="working-with-postgresql-compatibility-query-runtime"></a>

쿼리 런타임 데이터 유형은 쿼리 실행 시점에 사용되는 내부 데이터 유형입니다. 이러한 유형은 스키마에서 정의하는 `varchar` 및 `integer`와 같은 PostgreSQL 호환 유형과 다릅니다. 대신 이러한 유형은 Aurora DSQL이 쿼리를 처리할 때 사용하는 런타임 표현입니다.

다음 데이터 유형은 쿼리 런타임 중에만 지원됩니다.

**배열 유형**  
Aurora DSQL은 지원되는 데이터 유형의 배열을 지원합니다. 예를 들어 정수 배열이 있을 수 있습니다. `string_to_array` 함수는 다음 예시처럼 쉼표 구분 기호(`,`)를 사용하여 문자열을 PostgreSQL 스타일 배열로 분할합니다. 쿼리 실행 중에 표현식, 함수 출력 또는 임시 계산에 배열을 사용할 수 있습니다.  

```
SELECT string_to_array('1,2', ',');
```
이 함수는 다음과 유사한 응답을 반환합니다.  

```
 string_to_array 
-----------------
 {1,2}
(1 row)
```

****inet 유형****  
이 데이터 유형은 IPv4, IPv6 호스트 주소 및 해당 서브넷을 나타냅니다. 이 유형은 로그를 구문 분석하거나, IP 서브넷에서 필터링하거나, 쿼리 내에서 네트워크 계산을 수행할 때 유용합니다. 자세한 내용은 PostgreSQL 설명서의 [inet](https://www.PostgreSQL.org/docs/16/datatype-net-types.html#DATATYPE-INET)을 참조하세요.

**JSON 런타임 함수**  
Aurora DSQL은 쿼리 처리를 위한 런타임 데이터 유형으로 JSON 및 JSONB를 지원합니다. JSON 데이터를 `text` 열로 저장할 수 있으며 쿼리 실행 시 JSON으로 캐스팅하여 PostgreSQL JSON 함수와 연산자를 사용할 수 있습니다.  
Aurora DSQL은 [9.1.6 섹션 JSON 함수 및 연산자](https://www.postgresql.org/docs/current/functions-json.html)에 명시된 대부분의 PostgreSQL JSON 함수를 동일한 동작으로 지원합니다.  
JSON 또는 JSONB 유형을 반환하는 함수는 올바른 표시를 위해 `text`로 추가 형변환이 필요할 수 있습니다.  

```
SELECT json_build_array(1, 2, 'foo', 4, 5)::text;
```
이 함수는 다음과 유사한 응답을 반환합니다.  

```
     json_build_array
 ---------------------
   [1, 2, "foo", 4, 5]
 (1 row)
```

# Aurora DSQL에 지원되는 SQL
<a name="working-with-postgresql-compatibility-supported-sql-features"></a>

Aurora DSQL은 다양한 핵심 PostgreSQL SQL 기능을 지원합니다. 이어지는 섹션에서는 일반적인 PostgreSQL 표현식 지원에 대해 알아볼 수 있습니다. 단, 이 목록이 전부는 아닙니다.

## `SELECT` 명령
<a name="dsql-select"></a>

Aurora DSQL은 `SELECT` 명령의 다음 절을 지원합니다.


| 기본 절 | 지원 절 | 
| --- | --- | 
|  `FROM`  |    | 
|  `GROUP BY`  |  `ALL`, `DISTINCT`  | 
|  `ORDER BY`  |  `ASC`, `DESC`, `NULLS`  | 
|  `LIMIT`  |    | 
|  `DISTINCT`  |    | 
|  `HAVING`  |    | 
|  `USING`  |    | 
|  `WITH`(공통 테이블 표현식)  |    | 
|  `INNER JOIN`  |  `ON`  | 
|  `OUTER JOIN`  |  `LEFT`, `RIGHT`, `FULL`, `ON`  | 
|  `CROSS JOIN`  |  `ON`  | 
|  `UNION`  |  `ALL`  | 
|  `INTERSECT`  |  `ALL`  | 
|  `EXCEPT`  |  `ALL`  | 
|  `OVER`  |  `RANK ()`, `PARTITION BY`  | 
|  `FOR UPDATE`  |    | 

## 데이터 정의 언어(DDL)
<a name="dsql-ddl"></a>

Aurora DSQL은 다음과 같은 PostgreSQL DDL 명령을 지원합니다.


| Command | 기본 절 | 지원 절 | 
| --- | --- | --- | 
|  `CREATE`  |  `TABLE`  |  `CREATE TABLE` 명령의 지원되는 구문에 대한 자세한 내용은 [`CREATE TABLE`](create-table-syntax-support.md) 섹션을 참조하세요.  | 
|  `ALTER`  |  `TABLE`  |  `ALTER TABLE` 명령의 지원되는 구문에 대한 자세한 내용은 [`ALTER TABLE`](alter-table-syntax-support.md) 섹션을 참조하세요.  | 
|  `DROP`  |  `TABLE`  |    | 
|  `CREATE`  |  `[UNIQUE] INDEX ASYNC`  |  이 명령과 `ON`, `NULLS FIRST`, `NULLS LAST` 파라미터를 함께 사용할 수 있습니다. `CREATE INDEX ASYNC` 명령의 지원되는 구문에 대한 자세한 내용은 [Aurora DSQL의 비동기 인덱스](working-with-create-index-async.md) 섹션을 참조하세요.  | 
|  `DROP`  |  `INDEX`  |    | 
|  `CREATE`  |  `VIEW`  |  `CREATE VIEW` 명령의 지원되는 구문에 대한 자세한 내용은 [`CREATE VIEW`](create-view.md) 섹션을 참조하세요.  | 
| ALTER | VIEW |  `ALTER VIEW` 명령의 지원되는 구문에 대한 자세한 내용은 [`ALTER VIEW`](alter-view-syntax-support.md) 섹션을 참조하세요.  | 
| DROP | VIEW | DROP VIEW 명령의 지원되는 구문에 대한 자세한 내용은 [`DROP VIEW`](drop-view-overview.md) 섹션을 참조하세요. | 
|  `CREATE`  |  `SEQUENCE`  |  `CREATE SEQUENCE` 명령의 지원되는 구문에 대한 자세한 내용은 [`CREATE SEQUENCE`](create-sequence-syntax-support.md) 섹션을 참조하세요.  | 
|  `ALTER`  |  `SEQUENCE`  |  `ALTER SEQUENCE` 명령의 지원되는 구문에 대한 자세한 내용은 [`ALTER SEQUENCE`](alter-sequence-syntax-support.md) 섹션을 참조하세요.  | 
|  `DROP`  |  `SEQUENCE`  |  `DROP SEQUENCE` 명령의 지원되는 구문에 대한 자세한 내용은 [`DROP SEQUENCE`](drop-sequence-syntax-support.md) 섹션을 참조하세요.  | 
|  `CREATE`  |  `ROLE`, `WITH`  |    | 
|  `CREATE`  |  `FUNCTION`  |  `LANGUAGE SQL`  | 
|  `CREATE`  |  `DOMAIN`  |    | 

## 데이터 조작 언어(DML)
<a name="dsql-dml"></a>

Aurora DSQL은 다음과 같은 PostgreSQL DML 명령을 지원합니다.


| Command | 기본 절 | 지원 절 | 
| --- | --- | --- | 
|  `INSERT`  |  `INTO`  | `VALUES`SELECT | 
|  `UPDATE`  |  `SET`  |  `WHERE (SELECT)` `FROM, WITH`  | 
| DELETE | FROM | USING, WHERE | 

## 데이터 제어 언어(DCL)
<a name="dsql-dcl"></a>

Aurora DSQL은 다음과 같은 PostgreSQL DCL 명령을 지원합니다.


| Command | 지원 절 | 
| --- | --- | 
|  `GRANT`  |  `ON`, `TO`  | 
|  `REVOKE`  |  `ON`, `FROM`, `CASCADE`, `RESTRICT`  | 

## 트랜잭션 제어 언어(TCL)
<a name="dsql-tcl"></a>

Aurora DSQL은 다음과 같은 PostgreSQL TCL 명령을 지원합니다.


| Command | 지원 절 | 별칭 | 
| --- | --- | --- | 
|  `COMMIT`  |  [`WORK` \$1 `TRANSACTION`] [`AND NO CHAIN`]  |  `END`  | 
|  `BEGIN`  |  [`WORK` \$1 `TRANSACTION`] [`ISOLATION LEVEL REPEATABLE READ`] [`READ WRITE` \$1 `READ ONLY`]  |    | 
|  `START TRANSACTION`  |  [`ISOLATION LEVEL REPEATABLE READ`] [`READ WRITE` \$1 `READ ONLY`]  |    | 
|  `ROLLBACK`  |  [`WORK` \$1 `TRANSACTION`] [`AND NO CHAIN`]  |  `ABORT`  | 

## 유틸리티 명령
<a name="dsql-utility"></a>

Aurora DSQL은 다음과 같은 PostgreSQL 유틸리티 명령을 지원합니다.
+ `EXPLAIN`
+ `ANALYZE`(관계 이름만 해당)

# Aurora DSQL에서 지원되는 SQL 명령 하위 집합
<a name="working-with-postgresql-compatibility-supported-sql-subsets"></a>

이 섹션에서는 광범위한 파라미터 세트 및 하위 명령이 있는 명령에 중점을 두고 지원되는 SQL 명령에 대한 자세한 정보를 제공합니다. 예를 들어 PostgreSQL의 CREATE TABLE은 Aurora DSQL에서 지원하는 하위 집합인 여러 절과 파라미터를 제공합니다. 이 섹션에서는 Aurora DSQL이 지원하는 익숙한 PostgreSQL 구문 요소를 사용하여 지원되는 일반적인 SQL 명령의 하위 집합을 설명합니다.

**Topics**
+ [`CREATE TABLE`](create-table-syntax-support.md)
+ [`ALTER TABLE`](alter-table-syntax-support.md)
+ [`CREATE SEQUENCE`](create-sequence-syntax-support.md)
+ [`ALTER SEQUENCE`](alter-sequence-syntax-support.md)
+ [`DROP SEQUENCE`](drop-sequence-syntax-support.md)
+ [`CREATE VIEW`](create-view.md)
+ [`ALTER VIEW`](alter-view-syntax-support.md)
+ [`DROP VIEW`](drop-view-overview.md)

# `CREATE TABLE`
<a name="create-table-syntax-support"></a>

`CREATE TABLE`은 새 테이블을 정의합니다.

```
CREATE TABLE [ IF NOT EXISTS ] table_name ( [
  { column_name data_type [ column_constraint [ ... ] ]
    | table_constraint
    | LIKE source_table [ like_option ... ] }
    [, ... ]
] )

where column_constraint is:

[ CONSTRAINT constraint_name ]
{ NOT NULL |
  NULL |
  CHECK ( expression )|
  DEFAULT default_expr |
  GENERATED ALWAYS AS ( generation_expr ) STORED |
  GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY ( sequence_options ) |
  UNIQUE [ NULLS [ NOT ] DISTINCT ] index_parameters |
  PRIMARY KEY index_parameters |

and table_constraint is:

[ CONSTRAINT constraint_name ]
{ CHECK ( expression ) |
  UNIQUE [ NULLS [ NOT ] DISTINCT ] ( column_name [, ... ] ) index_parameters |
  PRIMARY KEY ( column_name [, ... ] ) index_parameters |

and like_option is:

{ INCLUDING | EXCLUDING } { COMMENTS | CONSTRAINTS | DEFAULTS | GENERATED | IDENTITY | INDEXES | STATISTICS | ALL }

index_parameters in UNIQUE, and PRIMARY KEY constraints are:
[ INCLUDE ( column_name [, ... ] ) ]
```

## ID 열
<a name="create-table-identity-columns"></a>

**참고**  
자격 증명 열을 사용할 때는 캐시 값을 신중하게 고려해야 합니다. 자세한 내용은 [`CREATE SEQUENCE`](create-sequence-syntax-support.md) 페이지의 중요 안내를 참조하세요.  
워크로드 패턴을 기반으로 자격 증명 열을 가장 잘 사용하는 방법에 대한 지침은 [시퀀스 및 자격 증명 열 작업](sequences-identity-columns-working-with.md) 섹션을 참조하세요.

`GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY ( sequence_options )` 절은 열을 *자격 증명 열*로 만듭니다. 암시적 시퀀스가 연결되고 새로 삽입된 행에서 열은 할당된 시퀀스의 값을 자동으로 갖습니다. 이러한 열은 암시적으로 `NOT NULL`입니다.

`ALWAYS` 및 `BY DEFAULT` 절은 `INSERT` 및 `UPDATE` 명령에서 사용자 지정 값을 명시적으로 처리하는 방법을 결정합니다.

`INSERT` 명령에서 `ALWAYS`가 선택된 경우 `INSERT` 문이 `OVERRIDING SYSTEM VALUE`를 지정하는 경우에만 사용자 지정 값이 허용됩니다. `BY DEFAULT`를 선택하면 사용자 지정 값이 우선합니다.

`UPDATE` 명령에서 `ALWAYS`가 선택된 경우 열을 이외의 값으로 업데이트하면 `DEFAULT`가 거부됩니다. `BY DEFAULT`를 선택하면 열을 정상적으로 업데이트할 수 있습니다. (`UPDATE`명령에는 `OVERRIDING` 절이 없습니다.)

*sequence\$1options* 절을 사용하여 시퀀스의 파라미터를 재정의할 수 있습니다. 사용 가능한 옵션에는 [`CREATE SEQUENCE`](create-sequence-syntax-support.md)에 대해 표시된 옵션과 `SEQUENCE NAME name`이 포함됩니다. `SEQUENCE NAME`이 없으면 시스템에서 시퀀스에 사용되지 않는 이름을 선택합니다.

# `ALTER TABLE`
<a name="alter-table-syntax-support"></a>

`ALTER TABLE`은 테이블의 정의를 변경합니다.

```
ALTER TABLE [ IF EXISTS ] [ ONLY ] name [ * ]
    action [, ... ]
ALTER TABLE [ IF EXISTS ] [ ONLY ] name [ * ]
    RENAME [ COLUMN ] column_name TO new_column_name
ALTER TABLE [ IF EXISTS ] [ ONLY ] name [ * ]
    RENAME CONSTRAINT constraint_name TO new_constraint_name
ALTER TABLE [ IF EXISTS ] name
    RENAME TO new_name
ALTER TABLE [ IF EXISTS ] name
    SET SCHEMA new_schema

where action is one of:

    ADD [ COLUMN ] [ IF NOT EXISTS ] column_name data_type
    ALTER [ COLUMN ] column_name { SET GENERATED { ALWAYS | BY DEFAULT } | SET sequence_option | RESTART [ [ WITH ] restart ] } [...]
    ALTER [ COLUMN ] column_name DROP IDENTITY [ IF EXISTS ]
    OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
```

## 자격 증명 열 작업
<a name="alter-table-identity-columns"></a>

**`SET GENERATED { ALWAYS | BY DEFAULT }` / `SET sequence_option` / `RESTART`**  
이러한 양식은 열이 자격 증명 열인지 아니면 기존 자격 증명 열의 생성 속성을 변경하는지 여부를 변경합니다. 세부 정보는 [`CREATE TABLE`](create-table-syntax-support.md) 섹션을 참조하세요. `SET DEFAULT`와 마찬가지로 이러한 형식은 후속 `INSERT` 및 `UPDATE` 명령의 동작에만 영향을 미치며 테이블에 이미 있는 행은 변경되지 않습니다.  
*sequence\$1option*은 `INCREMENT BY`와 같이 [`ALTER SEQUENCE`](alter-sequence-syntax-support.md)에서 지원하는 옵션입니다. 이러한 형식은 기존 자격 증명 열의 기반이 되는 시퀀스를 변경합니다.

**`DROP IDENTITY [ IF EXISTS ]`**  
이 양식은 열에서 자격 증명 속성을 제거합니다. `DROP IDENTITY IF EXISTS`가 지정되어 있고 열이 자격 증명 열이 아닌 경우 오류가 발생하지 않습니다. 이 경우 대신 알림이 발행됩니다.

# `CREATE SEQUENCE`
<a name="create-sequence-syntax-support"></a>

`CREATE SEQUENCE` - 새 시퀀스 생성기를 정의합니다.

**중요**  
PostgreSQL에서 `CACHE` 지정은 선택 사항이며 기본값은 1입니다. Amazon Aurora DSQL과 같은 분산 시스템에서 시퀀스 작업은 조정을 포함하며, 캐시 크기가 1이면 동시성이 높을 때 조정 오버헤드가 증가할 수 있습니다. 캐시 값이 크면 로컬에 미리 할당된 범위에서 시퀀스 번호를 제공할 수 있으므로, 처리량이 향상되고 사용하지 않는 예약 값이 손실되어 간격과 순서 지정 효과를 더 명확하게 확인할 수 있습니다. 애플리케이션마다 할당 순서와 처리량에 대한 민감도가 다르기 때문에 Amazon Aurora DSQL은 `CACHE`를 명시적으로 지정하도록 요구하며, 현재 `CACHE = 1` 또는 `CACHE >= 65536`을 지원하므로 엄격한 순차 생성에 더 가까운 할당 동작과 높은 동시성 워크로드에 최적화된 할당을 명확히 구분하도록 해 줍니다.  
`CACHE >= 65536`인 경우 시퀀스 값은 고유하게 유지되지만 세션 간에 엄격하게 증가하는 순서로 생성되지 않을 수 있으며, 특히 캐시된 값이 완전히 사용되지 않는 경우 간격이 발생할 수 있습니다. 이러한 특성은 동시 사용 시 캐시된 시퀀스에 대한 PostgreSQL 의미 체계와 일치하며, 두 시스템 모두 고유한 값을 보장하지만 세션 간에 엄격하게 순차적인 순서 지정을 보장하지는 않습니다.  
단일 클라이언트 세션 내에서 시퀀스 값은 특히 명시적 트랜잭션 외부에서 항상 엄격하게 증가하는 것처럼 보이지 않을 수 있습니다. 이 동작은 연결 풀링을 사용하는 PostgreSQL 배포와 유사합니다. 단일 세션 PostgreSQL 환경에 더 가까운 할당 동작은 `CACHE = 1`을 사용하거나 명시적 트랜잭션 내에서 시퀀스 값을 가져와 달성할 수 있습니다.  
`CACHE = 1`을 사용하면 시퀀스 할당이 PostgreSQL의 캐시되지 않은 시퀀스 동작을 따릅니다.  
워크로드 패턴을 기반으로 시퀀스를 가장 잘 사용하는 방법에 대한 지침은 [시퀀스 및 자격 증명 열 작업](sequences-identity-columns-working-with.md) 섹션을 참조하세요.

## 지원되는 구문
<a name="create-sequence-supported-syntax"></a>

```
CREATE SEQUENCE [ IF NOT EXISTS ] name CACHE cache
    [ AS data_type ]
    [ INCREMENT [ BY ] increment ]
    [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
    [ [ NO ] CYCLE ]
    [ START [ WITH ] start ]
    [ OWNED BY { table_name.column_name | NONE } ]

where data_type is BIGINT
      and cache = 1 or cache >= 65536
```

## 설명
<a name="create-sequence-description"></a>

`CREATE SEQUENCE`는 새 시퀀스 번호 생성기를 생성합니다. 여기에는 이름이 *name*인 새 특수 단일 행 테이블을 생성하고 초기화하는 작업이 포함됩니다. 명령을 실행하는 사용자가 생성기를 소유합니다.

스키마 이름이 제공되면 지정된 스키마에 시퀀스가 ​​생성됩니다. 그러지 않으면 현재 스키마에서 생성됩니다. 시퀀스 이름은 동일한 스키마 내의 다른 관계(테이블, 시퀀스, 인덱스, 뷰, 구체화된 뷰 또는 외부 테이블)의 이름과 달라야 합니다.

시퀀스가 생성되면 함수 `nextval`, `currval` 및 `setval`을 사용하여 시퀀스에서 작업합니다. 이러한 함수는 [시퀀스 조작 함수](sequence-functions-syntax-support.md)에 설명되어 있습니다.

시퀀스를 직접 업데이트할 수는 없지만 다음과 같은 쿼리를 사용할 수 있습니다.

```
SELECT * FROM name;
```

시퀀스의 일부 파라미터와 현재 상태를 검사합니다. 특히 시퀀스의 `last_value` 필드에는 세션에서 할당한 마지막 값이 표시됩니다. (물론 다른 세션이 적극적으로 `nextval` 직접 호출을 수행하는 경우 이 값은 출력되는 시점에 더 이상 사용되지 않을 수 있습니다.) `pg_sequences` 뷰에서 *increment* 및 *maxvalue*와 같은 다른 파라미터를 관찰할 수 있습니다.

## 파라미터
<a name="create-sequence-parameters"></a>

**`IF NOT EXISTS`**  
동일한 이름의 관계가 이미 있는 경우 오류를 발생시키지 않습니다. 이 경우 알림이 발행됩니다. 기존 관계가 생성되었을 시퀀스와 비슷하다는 보장은 없으며 시퀀스가 아닐 수도 있습니다.

*** 이름***  
생성할 시퀀스의 이름(선택적으로 스키마 한정자 포함)입니다.

***data\$1type***  
선택적 절 `AS data_type`은 시퀀스의 데이터 형식을 지정합니다. 유효한 값은 `bigint`이며, `bigint`가 기본값입니다. 데이터 형식에 따라 시퀀스의 기본 최솟값과 최댓값이 결정됩니다.

***increment***  
선택적 절 `INCREMENT BY increment`은 새 값을 생성하기 위해 현재 시퀀스 값에 추가할 값을 지정합니다. 양수 값은 오름차순 시퀀스를 만들고, 음수 값은 내림차순 시퀀스를 만듭니다. 기본값은 1입니다.

***minvalue* / `NO MINVALUE`**  
선택적 절 `MINVALUE minvalue`는 시퀀스가 생성할 수 있는 최솟값을 결정합니다. 이 절이 제공되지 않거나 `NO MINVALUE`가 지정된 경우 기본값이 사용됩니다. 오름차순 시퀀스의 기본값은 1입니다. 내림차순 시퀀스의 기본값은 데이터 형식의 최솟값입니다.

***maxvalue* / `NO MAXVALUE`**  
선택적 절 `MAXVALUE maxvalue`는 시퀀스의 최댓값을 결정합니다. 이 절이 제공되지 않거나 `NO MAXVALUE`가 지정된 경우 기본값이 사용됩니다. 오름차순 시퀀스의 기본값은 데이터 형식의 최댓값입니다. 내림차순 시퀀스의 기본값은 -1입니다.

**`CYCLE` / `NO CYCLE`**  
`CYCLE` 옵션을 사용하면 각각 오름차순 또는 내림차순 시퀀스에 의해 *maxvalue* 또는 *minvalue*에 도달했을 때 시퀀스를 래핑할 수 있습니다. 한도에 도달하면 생성되는 다음 숫자는 각각 *minvalue* 또는 *maxvalue*가 됩니다.  
`NO CYCLE`이 지정된 경우 시퀀스가 최댓값에 도달한 후 `nextval`을 직접적으로 호출하면 오류가 반환됩니다. `CYCLE` 및 `NO CYCLE`을 둘 다 지정하지 않으면 `NO CYCLE`이 기본값입니다.

***시작***  
선택적 절 `START WITH start`를 사용하면 어디서나 시퀀스를 시작할 수 있습니다. 기본 시작 값은 오름차순 시퀀스의 경우 *minvalue*이고 내림차순 시퀀스의 경우 *maxvalue*입니다.

***cache***  
절 `CACHE cache`는 더 빠른 액세스를 위해 사전 할당되고 메모리에 저장될 시퀀스 번호의 수를 지정합니다. Aurora DSQL에서 `CACHE`에 허용되는 값은 1 또는 65,536 이상의 모든 숫자입니다. 최솟값은 1입니다(한 번에 하나의 값만 생성할 수 있으므로 캐시가 없음).

**`OWNED BY table_name.column_name` / `OWNED BY NONE`**  
`OWNED BY` 옵션을 사용하면 시퀀스가 특정 테이블 열과 연결되므로 해당 열(또는 전체 테이블)이 삭제되면 시퀀스도 자동으로 삭제됩니다. 지정된 테이블은 소유자가 동일해야 하며 시퀀스와 동일한 스키마에 있어야 합니다. 기본값인 `OWNED BY NONE`은 이러한 연결이 없음을 지정합니다.

## 참고
<a name="create-sequence-notes"></a>

[`DROP SEQUENCE`](drop-sequence-syntax-support.md)를 사용하여 시퀀스를 제거합니다.

시퀀스는 `bigint` 산술을 기반으로 하므로 범위는 8바이트 정수(-9,223,372,036,854,775,808\$19,223,372,036,854,775,807)의 범위를 초과할 수 없습니다.

`nextval` 및 `setval` 직접 호출은 롤백되지 않으므로 시퀀스 번호의 ‘간격 없는’ 할당이 필요한 경우 시퀀스 객체를 사용할 수 없습니다.

각 세션은 시퀀스 객체에 대한 한 번의 액세스 중에 연속 시퀀스 값을 할당 및 캐싱하고 그에 따라 시퀀스 객체의 `last_value`를 늘립니다. 그런 다음 해당 세션 내에서 다음번에 `nextval`을 *cache*-1번 사용하면 시퀀스 객체를 터치하지 않고 미리 할당된 값을 반환하기만 합니다. 따라서 세션 내에서 할당되었지만 사용되지 않은 모든 숫자는 해당 세션이 종료될 때 손실되어 시퀀스에서 '구멍'이 됩니다.

또한 여러 세션이 고유한 시퀀스 값을 할당하도록 보장되지만 모든 세션이 고려되면 값이 시퀀스를 벗어나 생성될 수 있습니다. 예를 들어 *cache* 설정이 10인 경우 세션 A가 값 1..10을 예약하고 `nextval`=1을 반환한 다음, 세션 B는 세션 A가 `nextval`=2를 생성하기 전에 값 11..20을 예약하고 `nextval`=11을 반환할 수 있습니다. 따라서 *cache* 설정이 1이면 `nextval` 값이 순차적으로 생성된다고 가정하는 것이 안전합니다. *cache* 설정이 1보다 크면 `nextval` 값이 순차적으로만 생성되지 않고 모두 고유하다고 가정해야 합니다. 또한 `last_value`는 `nextval`에서 아직 반환했는지 여부에 관계없이 모든 세션에서 예약한 최신 값을 반영합니다.

또 다른 고려 사항은 이러한 시퀀스에서 실행된 `setval`은 캐싱된 미리 할당된 값을 모두 사용할 때까지 다른 세션에서 인식되지 않는다는 것입니다.

## 예제
<a name="create-sequence-examples"></a>

101부터 시작하여 `serial`이라는 오름차순 시퀀스를 생성합니다.

```
CREATE SEQUENCE serial CACHE 65536 START 101;
```

이 시퀀스에서 다음 번호를 선택합니다.

```
SELECT nextval('serial');

 nextval
---------
     101
```

이 시퀀스에서 다음 번호를 선택합니다.

```
SELECT nextval('serial');

 nextval
---------
     102
```

`INSERT` 명령에서 이 시퀀스를 사용합니다.

```
INSERT INTO distributors VALUES (nextval('serial'), 'nothing');
```

`setval`을 사용하여 시퀀스를 특정 값으로 재설정합니다.

```
SELECT setval('serial', 200);
SELECT nextval('serial');

 nextval
---------
     201
```

## 호환성
<a name="create-sequence-compatibility"></a>

`CREATE SEQUENCE`는 SQL 표준을 준수합니다. 단, 다음은 예외입니다.
+ 다음 값 가져오기는 표준 `NEXT VALUE FOR` 표현식 대신 `nextval()` 함수를 사용하여 수행됩니다.
+ `OWNED BY` 절은 PostgreSQL 확장입니다.

# `ALTER SEQUENCE`
<a name="alter-sequence-syntax-support"></a>

`ALTER SEQUENCE` - 시퀀스 생성기의 정의를 변경합니다.

**중요**  
시퀀스를 사용할 때는 캐시 값을 신중하게 고려해야 합니다. 자세한 내용은 [`CREATE SEQUENCE`](create-sequence-syntax-support.md) 페이지의 중요 안내를 참조하세요.  
워크로드 패턴을 기반으로 시퀀스를 가장 잘 사용하는 방법에 대한 지침은 [시퀀스 및 자격 증명 열 작업](sequences-identity-columns-working-with.md) 섹션을 참조하세요.

## 지원되는 구문
<a name="alter-sequence-supported-syntax"></a>

```
ALTER SEQUENCE [ IF EXISTS ] name
    [ INCREMENT [ BY ] increment ]
    [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
    [ [ NO ] CYCLE ]
    [ START [ WITH ] start ]
    [ RESTART [ [ WITH ] restart ] ]
    [ CACHE cache ]
    [ OWNED BY { table_name.column_name | NONE } ]
ALTER SEQUENCE [ IF EXISTS ] name OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
ALTER SEQUENCE [ IF EXISTS ] name RENAME TO new_name
ALTER SEQUENCE [ IF EXISTS ] name SET SCHEMA new_schema

where cache is 1 or cache >= 65536
```

## 설명
<a name="alter-sequence-description"></a>

`ALTER SEQUENCE`는 기존 시퀀스 생성기의 파라미터를 변경합니다. `ALTER SEQUENCE` 명령에 구체적으로 설정되지 않은 파라미터는 이전 설정을 유지합니다.

`ALTER SEQUENCE`를 사용하려면 시퀀스를 소유해야 합니다. 시퀀스의 스키마를 변경하려면 새 스키마에 대한 `CREATE` 권한도 있어야 합니다. 소유자를 변경하려면 새 소유 역할에 `SET ROLE`을 수행할 수 있어야 하며 해당 역할에 시퀀스의 스키마에 대한 `CREATE` 권한이 있어야 합니다. (이러한 제한은 소유자를 변경해도 시퀀스를 삭제하고 다시 생성하여 수행할 수 없는 작업은 수행하지 않도록 강제합니다. 그러나 수퍼유저는 어떤 시퀀스의 소유권도 변경할 수 있습니다.)

## 파라미터
<a name="alter-sequence-parameters"></a>

***이름***  
변경할 시퀀스의 이름(선택적으로 스키마 한정자 포함)입니다.

**`IF EXISTS`**  
시퀀스가 없는 경우 오류가 발생하지 않습니다. 이 경우 알림이 발행됩니다.

***increment***  
`INCREMENT BY increment` 절은 선택 사항입니다. 양수 값은 오름차순 시퀀스를 만들고, 음수 값은 내림차순 시퀀스를 만듭니다. 지정하지 않으면 이전 증분 값이 유지됩니다.

***minvalue* / `NO MINVALUE`**  
선택적 절 `MINVALUE minvalue`는 시퀀스가 생성할 수 있는 최솟값을 결정합니다. `NO MINVALUE`를 지정하면 오름차순 및 내림차순 시퀀스에 대해 1 및 해당 데이터 형식의 최솟값이 기본값으로 각각 사용됩니다. 두 옵션을 모두 지정하지 않으면 현재 최솟값이 유지됩니다.

***maxvalue* / `NO MAXVALUE`**  
선택적 절 `MAXVALUE maxvalue`는 시퀀스의 최댓값을 결정합니다. `NO MAXVALUE`를 지정하면 오름차순 및 내림차순 시퀀스에 대해 해당 데이터 형식의 최댓값과 -1이 기본값으로 각각 사용됩니다. 두 옵션을 모두 지정하지 않으면 현재 최댓값이 유지됩니다.

**`CYCLE`**  
선택적 `CYCLE` 키워드를 사용하여 각각 오름차순 또는 내림차순 시퀀스에 의해 *maxvalue* 또는 *minvalue*에 도달했을 때 시퀀스를 래핑할 수 있습니다. 한도에 도달하면 생성되는 다음 숫자는 각각 *minvalue* 또는 *maxvalue*가 됩니다.

**`NO CYCLE`**  
선택적 `NO CYCLE` 키워드가 지정된 경우 시퀀스가 최댓값에 도달한 후 `nextval`을 직접적으로 호출하면 오류가 반환됩니다. `CYCLE` 및 `NO CYCLE`를 모두 지정하지 않으면 이전 주기 동작이 유지됩니다.

***시작***  
선택적 절 `START WITH start`는 시퀀스의 기록된 시작 값을 변경합니다. 이는 현재 시퀀스 값에 영향을 주지 않으며, 향후 `ALTER SEQUENCE RESTART` 명령에서 사용할 값을 설정하기만 합니다.

***재시작***  
선택적 절 `RESTART [ WITH restart ]`는 시퀀스의 현재 값을 변경합니다. 이는 `is_called` = `false`로 `setval` 함수를 직접적으로 호출하는 것과 유사합니다. 지정된 값은 `nextval`의 다음 직접 호출에 의해 반환됩니다. *restart* 값 없이 `RESTART`를 쓰는 것은 `CREATE SEQUENCE`에서 기록했거나 `ALTER SEQUENCE START WITH`에서 마지막으로 설정한 시작 값을 제공하는 것과 같습니다.  
`setval` 직접 호출과 달리 시퀀스에 대한 `RESTART` 작업은 트랜잭션이며 동시 트랜잭션이 동일한 시퀀스에서 번호를 얻는 것을 차단합니다. 원하는 작업 모드가 아닌 경우 `setval`을 사용해야 합니다.

***cache***  
절 `CACHE cache`를 사용하면 더 빠른 액세스를 위해 시퀀스 번호를 미리 할당하고 메모리에 저장할 수 있습니다. 값은 1이거나 65,536 이상이어야 합니다. 지정하지 않으면 이전 캐시 값이 유지됩니다. 캐시 동작에 대한 자세한 내용은 [`CREATE SEQUENCE`](create-sequence-syntax-support.md) 아래의 지침을 참조하세요.

**`OWNED BY table_name.column_name` / `OWNED BY NONE`**  
`OWNED BY` 옵션을 사용하면 시퀀스가 특정 테이블 열과 연결되므로 해당 열(또는 전체 테이블)이 삭제되면 시퀀스도 자동으로 삭제됩니다. 지정된 경우 이 연결은 시퀀스에 대해 이전에 지정된 연결을 대체합니다. 지정된 테이블은 소유자가 동일해야 하며 시퀀스와 동일한 스키마에 있어야 합니다. `OWNED BY NONE`를 지정하면 기존 연결이 제거되어 시퀀스가 ‘독립적으로 존재하는 상태’가 됩니다.

***new\$1owner***  
새 시퀀스 소유자의 사용자 이름입니다.

***new\$1name***  
시퀀스의 새 이름입니다.

***new\$1schema***  
시퀀스의 새 스키마입니다.

## 참고
<a name="alter-sequence-notes"></a>

`ALTER SEQUENCE`는 사전 할당된(캐싱된) 시퀀스 값이 있는 현재 백엔드를 제외하면 백엔드의 `nextval` 결과에 즉시 영향을 미치지 않습니다. 변경된 시퀀스 생성 파라미터를 확인하기 전에 캐시된 모든 값을 사용합니다. 현재 백엔드는 즉시 영향을 받습니다.

`ALTER SEQUENCE`는 시퀀스의 `currval` 상태에 영향을 주지 않습니다.

`ALTER SEQUENCE`는 다른 트랜잭션을 OCC로 만들 수 있습니다.

기록상 이유로 시퀀스에도 `ALTER TABLE`을 사용할 수 있지만, 시퀀스에서 허용되는 `ALTER TABLE`의 유일한 변형은 위에 표시된 형식과 동일합니다.

## 예제
<a name="alter-sequence-examples"></a>

105에서 `serial`이라는 시퀀스를 다시 시작합니다.

```
ALTER SEQUENCE serial RESTART WITH 105;
```

## 호환성
<a name="alter-sequence-compatibility"></a>

`ALTER SEQUENCE`는 PostgreSQL 확장인 `AS`, `START WITH`, `OWNED BY`, `OWNER TO`, `RENAME TO`, `SET SCHEMA` 절을 제외하고 SQL 표준을 준수합니다.

# `DROP SEQUENCE`
<a name="drop-sequence-syntax-support"></a>

`DROP SEQUENCE` - 시퀀스를 제거합니다.

## 지원되는 구문
<a name="drop-sequence-supported-syntax"></a>

```
DROP SEQUENCE [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
```

## 설명
<a name="drop-sequence-description"></a>

`DROP SEQUENCE`는 시퀀스 번호 생성기를 제거합니다. 시퀀스는 소유자 또는 수퍼유저만 삭제할 수 있습니다.

## 파라미터
<a name="drop-sequence-parameters"></a>

**`IF EXISTS`**  
시퀀스가 없는 경우 오류가 발생하지 않습니다. 이 경우 알림이 발행됩니다.

*** 이름***  
시퀀스의 이름(선택적으로 스키마 한정자 포함)입니다.

**`CASCADE`**  
확장에 종속된 객체와 해당 객체에 종속된 모든 객체가 자동으로 삭제됩니다.

**`RESTRICT`**  
종속된 객체가 있는 경우 시퀀스를 삭제하는 것을 거부합니다. 이 값이 기본값입니다.

## 예제
<a name="drop-sequence-examples"></a>

`seq` 시퀀스 제거:

```
DROP SEQUENCE seq;
```

## 호환성
<a name="drop-sequence-compatibility"></a>

`DROP SEQUENCE`는 SQL 표준을 준수합니다. 그러나 표준에서는 명령당 하나의 시퀀스만 삭제할 수 있으며 PostgreSQL 확장 기능인 `IF EXISTS` 옵션이 제외되어 있다는 점이 다릅니다.

# `CREATE VIEW`
<a name="create-view"></a>

`CREATE VIEW`는 새로운 영구 뷰를 정의합니다. Aurora DSQL은 임시 뷰를 지원하지 않으며 영구 뷰만 지원됩니다.

## 지원되는 구문
<a name="create-view-supported-syntax"></a>

```
CREATE [ OR REPLACE ] [ RECURSIVE ] VIEW name [ ( column_name [, ...] ) ]
    [ WITH ( view_option_name [= view_option_value] [, ... ] ) ]
    AS query
    [ WITH [ CASCADED | LOCAL ] CHECK OPTION ]
```

## 설명
<a name="create-view-description"></a>

`CREATE VIEW`는 쿼리 뷰를 정의합니다. 이 뷰는 물리적으로 구체화되지 않습니다. 대신 쿼리에서 뷰가 참조될 때마다 쿼리가 실행됩니다.

`CREATE or REPLACE VIEW`는 비슷하지만 동일한 이름의 뷰가 이미 있는 경우 대체됩니다. 새 쿼리는 기존 뷰 쿼리에서 생성된 것과 동일한 열(즉, 동일한 순서로 동일한 데이터 유형을 가진 동일한 열 이름)을 생성해야 하지만 목록 끝에 추가 열을 추가할 수 있습니다. 출력 열을 생성하는 계산은 다를 수 있습니다.

스키마 이름이 지정되어 있는 경우(예: `CREATE VIEW myschema.myview ...`), 뷰는 지정된 스키마에서 생성됩니다. 그렇지 않으면, 뷰가 현재 스키마에서 생성됩니다.

뷰의 이름은 동일한 스키마에 있는 다른 관계(테이블, 인덱스, 뷰)의 이름과 달라야 합니다.

## 파라미터
<a name="create-view-parameters"></a>

`CREATE VIEW`는 다양한 파라미터를 지원하여 자동으로 업데이트 가능한 뷰의 동작을 제어합니다.

**`RECURSIVE`**  
재귀 뷰를 생성합니다. `CREATE RECURSIVE VIEW [ schema . ] view_name (column_names) AS SELECT ...;` 구문은 `CREATE VIEW [ schema . ] view_name AS WITH RECURSIVE view_name (column_names) AS (SELECT ...) SELECT column_names FROM view_name;`과 동일합니다.  
재귀 뷰에 대해 뷰 열 이름 목록을 지정해야 합니다.

**`name`**  
생성할 뷰의 이름으로, 선택적으로 스키마가 지정될 수 있습니다. 재귀 뷰에 열 이름 목록을 지정해야 합니다.

**`column_name`**  
뷰에서 열에 사용할 이름의 선택적 목록입니다. 지정되지 않은 경우에는 열 이름이 쿼리에서 추론됩니다.

**`WITH ( view_option_name [= view_option_value] [, ... ] )`**  
이 절은 뷰에 대한 선택적 파라미터를 지정합니다. 다음 파라미터가 지원됩니다.  
+ `check_option (enum)` -이 파라미터는 `local` 또는 `cascaded`일 수 있으며 `WITH [ CASCADED | LOCAL ] CHECK OPTION` 지정과 동일합니다.
+ `security_barrier (boolean)` - 뷰가 행 수준 보안을 제공해야 하는 경우 이 옵션을 사용해야 합니다. Aurora DSQL은 현재 행 수준 보안을 지원하지 않지만 이 옵션은 뷰의 `WHERE` 조건(및 `LEAKPROOF`로 표시된 연산자를 사용하는 모든 조건)을 먼저 평가하도록 강제합니다.
+ `security_invoker (boolean)` -이 옵션을 사용하면 뷰 소유자가 아닌 뷰 사용자의 권한을 기준으로 기본 관계를 확인할 수 있습니다. 자세한 내용은 아래 참고 사항을 참조하세요.
위의 모든 옵션은 기존 뷰에서 `ALTER VIEW`를 사용하여 변경할 수 있습니다.

**`query`**  
뷰의 열과 행을 제공하는 `SELECT` 또는 `VALUES` 명령입니다.

**`WITH [ CASCADED | LOCAL ] CHECK OPTION`**  
이 옵션은 자동으로 업데이트 가능한 뷰의 동작을 제어합니다. 이 옵션을 지정하면 새 행이 뷰 정의 조건을 충족하는지 확인하기 위해 뷰의 `INSERT` 및 `UPDATE` 명령이 확인됩니다(즉, 새 행이 뷰를 통해 표시되는지 확인함). 충족하지 않으면 업데이트가 거부됩니다. `CHECK OPTION`이 지정되지 않은 경우 뷰의 `INSERT` 및 `UPDATE` 명령은 뷰를 통해 표시되지 않는 행을 생성할 수 있습니다.  
`LOCAL` - 새 행은 뷰 자체에 직접 정의된 조건을 기준으로만 확인됩니다. 기본 뷰에 정의된 조건은 아무것도 확인되지 않습니다(`CHECK OPTION`을 지정하지 않는 한).  
`CASCADED` - 뷰 및 모든 기본 뷰의 조건을 기준으로 새 행이 확인됩니다. `CHECK OPTION`이 지정되고 `LOCAL`과 `CASCADED`는 지정되지 않으면 `CASCADED`가 수임됩니다.  
`CHECK OPTION`은 `RECURSIVE` 뷰와 함께 사용할 수 없습니다. `CHECK OPTION`은 자동으로 업데이트 가능한 뷰에서만 지원됩니다.

## 참고
<a name="create-view-notes"></a>

`DROP VIEW` 문을 사용하여 뷰를 삭제합니다.

뷰 열의 이름과 데이터 유형을 신중하게 고려해야 합니다. 예를 들어 CREATE VIEW vista AS SELECT 'Hello World';는 열 이름의 기본값이 `?column?;`이므로 권장되지 않습니다. 또한 열 데이터 유형은 기본적으로 `text`로 설정되며, 이는 원하는 것과 다를 수 있습니다.

더 나은 방법은 `CREATE VIEW vista AS SELECT text 'Hello World' AS hello;`와 같이 열 이름과 데이터 유형을 명시적으로 지정하는 것입니다.

기본적으로 뷰에서 참조되는 기본 관계에 대한 액세스는 뷰 소유자의 권한에 따라 결정됩니다. 경우에 따라 기본 테이블에 대한 안전하고 제한된 액세스를 제공하는 데 사용할 수 있습니다. 그러나 모든 뷰가 변조로부터 안전한 것은 아닙니다.
+ 뷰에 `security_invoker` 속성이 true로 설정된 경우 기본 관계에 대한 액세스는 뷰 소유자가 아닌 쿼리를 실행하는 사용자의 권한에 따라 결정됩니다. 따라서 보안 호출자 뷰의 사용자는 뷰 및 기본 관계에 대한 관련 권한이 있어야 합니다.
+ 기본 관계가 보안 호출자 뷰인 경우 원래 쿼리에서 직접 액세스한 것처럼 처리됩니다. 따라서 보안 호출자 뷰는 `security_invoker` 속성이 없는 뷰에서 액세스하더라도 항상 현재 사용자의 권한을 사용하여 기본 관계를 확인합니다.
+ 뷰에서 직접 호출된 함수는 뷰를 사용하여 쿼리에서 직접 호출된 것과 동일하게 처리됩니다. 따라서 뷰 사용자에게 뷰에서 사용하는 모든 함수를 직접 호출할 수 있는 권한이 있어야 합니다. 뷰의 함수는 함수가 `SECURITY INVOKER`와 `SECURITY DEFINER` 중 무엇으로 정의되었는지에 따라 쿼리를 실행하는 사용자 또는 함수 소유자의 권한으로 실행됩니다.
+ 뷰를 생성하거나 교체하는 사용자는 스키마에서 참조된 객체를 조회하기 위해 뷰 쿼리에서 참조된 스키마에 대한 `USAGE` 권한이 있어야 합니다.
+ 기존 뷰에서 `CREATE OR REPLACE VIEW`를 사용하는 경우 뷰의 정의 `SELECT` 규칙과 `WITH ( ... )` 파라미터 및 해당 `CHECK OPTION`만 변경됩니다. 소유권, 권한 및 SELECT가 아닌 규칙을 포함한 다른 뷰 속성은 변경되지 않습니다. 뷰를 대체하려면 뷰를 소유해야 합니다(소유 역할의 멤버가 되는 것 포함).

## 업데이트 가능한 뷰
<a name="create-view-updatable-view"></a>

단순 뷰는 자동으로 업데이트할 수 있습니다. 시스템에서는 일반 테이블과 동일한 방식으로 뷰에서 `INSERT`, `UPDATE` 및 `DELETE` 문을 사용하도록 허용합니다. 뷰는 다음 조건을 모두 충족하는 경우 자동으로 업데이트됩니다.
+ 뷰는 `FROM` 목록에 정확히 하나의 항목이 있어야 하며,이 항목은 테이블 또는 다른 업데이트 가능한 뷰여야 합니다.
+ 뷰 정의에서 최상위 수준에 `WITH`, `DISTINCT`, `GROUP BY`, `HAVING`, `LIMIT` 또는 `OFFSET` 절이 포함되어서는 안 됩니다.
+ 뷰 정의에서 최상위 수준에 세트 작업(`UNION`, `INTERSECT` 또는 `EXCEPT`)이 포함되어서는 안 됩니다.
+ 뷰의 선택 목록에 집계, 창 함수 또는 집합 반환 함수가 포함되어서는 안 됩니다.

자동 업데이트 가능 뷰에 업데이트 가능 열과 업데이트 불가능 열이 혼합되어 있을 수 있습니다. 기본 관계의 업데이트 가능한 열에 대한 단순 참조인 경우 열을 업데이트할 수 있습니다. 그렇지 않으면 열은 읽기 전용이며 `INSERT` 또는 `UPDATE` 문이 값을 할당하려고 하면 오류가 발생합니다.

이 모든 조건을 충족하지 않는 보다 복잡한 뷰는 기본적으로 읽기 전용입니다. 시스템은 해당 뷰에서 삽입, 업데이트 또는 삭제를 허용하지 않습니다.

**참고**  
해당 뷰에서 삽입, 업데이트 또는 삭제를 수행하는 사용자에게는 뷰에 대한 해당 삽입, 업데이트 또는 삭제 권한이 있어야 합니다. 기본적으로 뷰의 소유자는 기본 관계에 대한 관련 권한을 가지고 있어야 하지만 업데이트를 수행하는 사용자는 기본 관계에 대한 권한이 필요하지 않습니다. 그러나 뷰에 security\$1invoker가 true로 설정된 경우 뷰 소유자가 아닌 업데이트를 수행하는 사용자에게 기본 관계에 대한 관련 권한이 있어야 합니다.

## 예제
<a name="create-view-examples"></a>

모든 코미디 영화로 구성된 뷰를 생성합니다.

```
CREATE VIEW comedies AS
    SELECT *
    FROM films
    WHERE kind = 'Comedy';
```

`LOCAL CHECK OPTION`을 포함하여 뷰를 생성합니다.

```
CREATE VIEW pg_comedies AS
    SELECT *
    FROM comedies
    WHERE classification = 'PG'
    WITH CASCADED CHECK OPTION;
```

재귀 뷰를 생성합니다.

```
CREATE RECURSIVE VIEW public.nums_1_100 (n) AS
    VALUES (1)
UNION ALL
    SELECT n+1 FROM nums_1_100 WHERE n < 100;
```

## 호환성
<a name="create-view-compatibility"></a>

`CREATE OR REPLACE VIEW`는 PostgreSQL 언어 확장입니다. `WITH ( ... )` 절도 확장이며 보안 장벽 뷰 및 보안 호출자 뷰도 마찬가지입니다. Aurora DSQL은 이러한 언어 확장을 지원합니다.

# `ALTER VIEW`
<a name="alter-view-syntax-support"></a>

`ALTER VIEW` 문을 사용하면 기존 뷰의 다양한 속성을 변경할 수 있으며 Aurora DSQL은 이 명령에 대한 모든 PostgreSQL 구문을 지원합니다.

## 지원되는 구문
<a name="alter-view-supported-syntax"></a>

```
ALTER VIEW [ IF EXISTS ] name ALTER [ COLUMN ] column_name SET DEFAULT expression
ALTER VIEW [ IF EXISTS ] name ALTER [ COLUMN ] column_name DROP DEFAULT
ALTER VIEW [ IF EXISTS ] name OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
ALTER VIEW [ IF EXISTS ] name RENAME [ COLUMN ] column_name TO new_column_name
ALTER VIEW [ IF EXISTS ] name RENAME TO new_name
ALTER VIEW [ IF EXISTS ] name SET SCHEMA new_schema
ALTER VIEW [ IF EXISTS ] name SET ( view_option_name [= view_option_value] [, ... ] )
ALTER VIEW [ IF EXISTS ] name RESET ( view_option_name [, ... ] )
```

## 설명
<a name="alter-view-description"></a>

`ALTER VIEW`는 뷰의 다양한 보조 속성을 변경합니다. (뷰의 정의 쿼리를 수정하려면 `CREATE OR REPLACE VIEW`를 사용합니다.) `ALTER VIEW`를 사용하려면 뷰를 소유해야 합니다. 뷰의 스키마를 변경하려면 새 스키마에 대한 `CREATE` 권한도 있어야 합니다. 소유자를 변경하려면 새 소유 역할에 `SET ROLE`을 수행할 수 있어야 하며 해당 역할에 뷰의 스키마에 대한 `CREATE` 권한이 있어야 합니다.

## 파라미터
<a name="alter-view-parameters"></a>

**`name`**  
기존 뷰의 이름(선택적으로 스키마 지정)입니다.

**`column_name`**  
기존 열의 이름 또는 기존 열의 새 이름입니다.

**`IF EXISTS`**  
뷰가 없는 경우 오류가 발생하지 않습니다. 이 경우 알림이 발행됩니다.

**`SET/DROP DEFAULT`**  
이러한 양식은 열의 기본값을 설정하거나 제거합니다. 뷰 열의 기본값은 대상이 뷰인 `INSERT` 또는 `UPDATE` 명령으로 대체됩니다.

**`new_owner`**  
뷰의 새 소유자의 사용자 이름입니다.

**`new_name`**  
새 뷰의 이름입니다.

**`new_schema`**  
뷰의 새 스키마입니다.

**`SET ( view_option_name [= view_option_value] [, ... ] )`**  
뷰 옵션을 설정합니다. 지원되는 옵션은 다음과 같습니다.  
+ `check_option (enum)` - 뷰의 확인 옵션을 변경합니다. 값은 `local` 또는 `cascaded`여야 합니다.
+ `security_barrier (boolean)` - 뷰의 보안 장벽 속성을 변경합니다.
+ `security_invoker (boolean)` - 뷰의 security-invoker 속성을 변경합니다.

**`RESET ( view_option_name [, ... ] )`**  
뷰 옵션을 기본값으로 재설정합니다.

## 예제
<a name="alter-view-examples"></a>

`foo` 뷰의 이름을 `bar`로 변경:

```
ALTER VIEW foo RENAME TO bar;
```

업데이트 가능한 뷰에 기본 열 값을 연결:

```
CREATE TABLE base_table (id int, ts timestamptz);
CREATE VIEW a_view AS SELECT * FROM base_table;
ALTER VIEW a_view ALTER COLUMN ts SET DEFAULT now();
INSERT INTO base_table(id) VALUES(1);  -- ts will receive a NULL
INSERT INTO a_view(id) VALUES(2);  -- ts will receive the current time
```

## 호환성
<a name="alter-view-compatibility"></a>

`ALTER VIEW`는 Aurora DSQL이 지원하는 SQL 표준의 PostgreSQL 확장입니다.

# `DROP VIEW`
<a name="drop-view-overview"></a>

`DROP VIEW` 문은 기존 뷰를 제거합니다. Aurora DSQL은 이 명령에 대한 전체 PostgreSQL 구문을 지원합니다.

## 지원되는 구문
<a name="drop-view-supported-syntax"></a>

```
DROP VIEW [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
```

## 설명
<a name="drop-view-description"></a>

`DROP VIEW`는 기존 뷰를 삭제합니다. 이 명령을 실행하려면 뷰의 소유자여야 합니다.

## Parameters
<a name="drop-view-parameters"></a>

**`IF EXISTS`**  
뷰가 없는 경우 오류가 발생하지 않습니다. 이 경우 알림이 발행됩니다.

**`name`**  
제거할 뷰의 이름(선택적으로 스키마 지정)입니다.

**`CASCADE`**  
뷰에 종속된 객체(예: 다른 뷰)와 해당 객체에 종속된 모든 객체가 자동으로 삭제됩니다.

**`RESTRICT`**  
종속된 객체가 있는 경우 뷰를 삭제하는 것을 거부합니다. 이 값이 기본값입니다.

## 예제
<a name="drop-view-examples"></a>

```
DROP VIEW kinds;
```

## 호환성
<a name="drop-view-compatibility"></a>

이 명령은 SQL 표준을 준수합니다. 단, Aurora DSQL이 지원하는 PostgreSQL 확장인 `IF EXISTS` 옵션을 제외하고 표준에서 명령당 하나의 뷰만 삭제할 수 있습니다.

# PostgreSQL에서 Aurora DSQL로 마이그레이션
<a name="working-with-postgresql-compatibility-migration-guide"></a>

Aurora DSQL은 [PostgreSQL과 호환](working-with-postgresql-compatibility.md)되도록 설계되었으며 ACID 트랜잭션, 보조 인덱스, 조인, 표준 DML 작업과 같은 핵심 관계형 기능을 지원합니다. 대부분의 기존 PostgreSQL 애플리케이션은 최소한의 변경으로 Aurora DSQL로 마이그레이션할 수 있습니다.

이 섹션에서는 프레임워크 호환성, 마이그레이션 패턴, 아키텍처 고려 사항을 포함하여 애플리케이션을 Aurora DSQL로 마이그레이션하기 위한 실용적인 지침을 제공합니다.

## 프레임워크 및 ORM 호환성
<a name="dsql-framework-compatibility"></a>

 Aurora DSQL은 표준 PostgreSQL 유선 프로토콜을 사용하므로 PostgreSQL 드라이버 및 프레임워크와 호환됩니다. 대부분의 인기 ORM은 변경 없이 또는 최소한의 변경만으로 Aurora DSQL과 호환됩니다. 참조 구현 및 사용 가능한 ORM 통합은 [Aurora DSQL 어댑터 및 방언](aws-sdks.md#aurora-dsql-adapters) 섹션을 참조하세요.

## 일반적인 마이그레이션 패턴
<a name="working-with-postgresql-compatibility-migration-considerations"></a>

 PostgreSQL에서 Aurora DSQL로 마이그레이션할 때 일부 기능은 다르게 작동하거나 대체 구문이 있습니다. 이 섹션에서는 일반적인 마이그레이션 시나리오에 대한 지침을 제공합니다.

### DDL 작업 대안
<a name="dsql-ddl-alternatives"></a>

Aurora DSQL은 기존 PostgreSQL DDL 작업에 대한 최신 대안을 제공합니다.

**인덱스 생성**  
비차단 인덱스를 생성하는 데 `CREATE INDEX` 대신 `CREATE INDEX ASYNC`를 사용합니다.  
**이점:** 큰 테이블에서 가동 중지 시간 없이 인덱스를 생성할 수 있습니다.

**데이터 제거**  
`TRUNCATE` 대신 `DELETE FROM table_name`를 사용합니다.  
**대안:** 테이블을 완전히 다시 생성하려면 `DROP TABLE`을 사용한 후 `CREATE TABLE`을 사용합니다.

**시스템 구성**  
Aurora DSQL은 완전 관리형이므로 구성이 워크로드 패턴에 따라 자동으로 처리됩니다. AWS Management Console 또는 API를 사용하여 클러스터 설정을 관리합니다.  
**이점:** 데이터베이스 튜닝이나 파라미터 관리가 필요하지 않습니다.

### 스키마 설계 패턴
<a name="dsql-schema-design-patterns"></a>

Aurora DSQL과의 호환성을 위해 다음과 같은 일반적인 PostgreSQL 패턴을 조정합니다.

**참조 무결성 패턴**  
Aurora DSQL은 테이블 관계 및 `JOIN` 작업을 지원합니다. 참조 무결성을 위해 애플리케이션 계층에서 검증을 구현합니다. 이러한 설계는 애플리케이션 계층 검증을 통해 유연성을 높이고 연쇄적 작업으로 인한 성능 병목 현상을 방지하는 최신 분산 데이터베이스 패턴과 일맥상통합니다.  
**패턴:** 일관된 이름 지정 규칙, 검증 로직 및 트랜잭션 경계를 사용하여 애플리케이션 계층에서 참조 무결성 검사를 구현하세요. 많은 대규모 애플리케이션은 오류 처리 및 성능을 더 잘 제어하기 위해 이 접근 방식을 선호합니다.

**임시 데이터 처리**  
임시 테이블 대신 CTE, 하위 쿼리 또는 정리 로직이 포함된 일반 테이블을 사용합니다.  
**대안:** 세션별 이름을 가진 테이블을 생성하고 애플리케이션 내에서 정리하세요.

## 아키텍처 차이점 이해
<a name="working-with-postgresql-compatibility-architectural-differences"></a>

Aurora DSQL의 분산 서버리스 아키텍처는 여러 면에서 기존 PostgreSQL과 의도적으로 다릅니다. 이러한 차이점을 통해 Aurora DSQL은 단순성과 확장성이라는 핵심적인 이점을 제공합니다.

### 간소화된 데이터베이스 모델
<a name="dsql-simplified-database-model"></a>

**클러스터당 단일 데이터베이스**  
Aurora DSQL은 클러스터마다 `postgres`라는 내장 데이터베이스 하나를 제공합니다.  
**마이그레이션 팁:** 애플리케이션에서 여러 데이터베이스를 사용하는 경우 논리적 분리를 위해 별도의 Aurora DSQL 클러스터를 생성하거나 단일 클러스터 내에서 스키마를 사용하세요.

**임시 테이블 미지원**  
 임시 데이터 처리를 위해서는 복잡한 쿼리에 대한 유연한 대안을 제공하는 공통 테이블 표현(CTE) 및 하위 쿼리를 사용해야 합니다.  
 **대안:** 임시 결과 집합의 경우 `WITH` 절과 함께 CTE를 사용하고, 세션별 데이터의 경우 고유한 이름이 지정된 일반 테이블을 사용할 수 있습니다.

**자동 스토리지 관리**  
Aurora DSQL을 사용하면 테이블스페이스 및 수동 스토리지 관리가 필요 없습니다. 스토리지는 데이터 패턴에 따라 자동으로 규모가 조정되고 최적화됩니다.  
**이점:** 디스크 공간을 모니터링하거나 스토리지 할당을 계획하거나 테이블스페이스 구성을 관리할 필요가 없습니다.

### 최신 애플리케이션 패턴
<a name="dsql-modern-application-patterns"></a>

Aurora DSQL은 유지 관리성과 성능을 향상시키는 최신 애플리케이션 개발 패턴을 장려합니다.

**데이터베이스 트리거 대신 애플리케이션 수준 로직**  
트리거와 같은 기능을 사용하려면 애플리케이션 계층에서 이벤트 기반 로직을 구현합니다.  
**마이그레이션 전략:** 트리거 로직을 애플리케이션 코드로 이동하거나, EventBridge와 같은 AWS 서비스와 함께 이벤트 기반 아키텍처를 사용하거나, 애플리케이션 로깅을 통해 감사 추적을 구현하세요.

**데이터 처리를 위한 SQL 함수**  
Aurora DSQL은 SQL 기반 함수를 지원하지만 PL/pgSQL과 같은 절차적 언어는 지원하지 않습니다.  
**대안:** 데이터 변환에 SQL 함수를 사용하거나, 복잡한 로직을 애플리케이션 계층 또는 AWS Lambda 함수로 이동하세요.

**수동적 잠금 대신 낙관적 동시성 제어**  
Aurora DSQL은 기존 데이터베이스 잠금 메커니즘과 다른, 잠금 없는 방식인 낙관적 동시성 제어(OCC)를 사용합니다. Aurora DSQL은 다른 트랜잭션을 차단하는 잠금을 획득하는 대신 차단 없이 트랜잭션이 진행되도록 하고 커밋 시 충돌을 감지합니다. 이를 통해 교착 상태를 방지하고 느린 트랜잭션이 다른 작업을 차단하는 것을 막습니다.  
**주요 차이점:** Aurora DSQL은 충돌이 발생할 경우 트랜잭션이 잠금을 기다리도록 하는 대신 직렬화 오류를 반환합니다. 이를 위해 애플리케이션이 기존 데이터베이스에서 잠금 제한 시간을 처리하는 것과 유사하게 재시도 로직을 구현해야 하지만, 충돌이 즉시 해결되어 차단 대기를 유발하지 않습니다.  
**설계 패턴:** 재시도 메커니즘을 갖춘 멱등성 트랜잭션 로직을 구현하세요. 무작위 프라이머리 키를 사용하고 키 범위 전체에 걸쳐 업데이트를 분산시켜 경합을 최소화하도록 스키마를 설계합니다. 자세한 내용은 [Aurora DSQL의 동시성 제어](working-with-concurrency-control.md)을 참조하세요.

**관계 및 참조 무결성**  
 Aurora DSQL은 ` JOIN ` 연산을 포함한 테이블 간의 외래 키 관계를 지원합니다. 참조 무결성을 위해 애플리케이션 계층에서 검증을 구현합니다. 참조 무결성을 적용하는 것은 중요할 수 있지만 연쇄적 작업(예: 연쇄 삭제)은 예기치 않은 성능 문제를 일으킬 수 있습니다. 예를 들어, 1,000개의 품목이 있는 주문을 삭제하는 경우 1,001개의 행을 처리하는 트랜잭션이 실행됩니다. 이러한 이유로 많은 고객이 외래 키 제약 조건을 피합니다.  
**설계 패턴:** 애플리케이션 계층에서 참조 무결성 검사를 구현하거나, 최종 일관성 패턴을 사용하거나, AWS 서비스를 활용하여 데이터를 검증하세요.

### 운영 간소화
<a name="dsql-operational-simplifications"></a>

Aurora DSQL을 사용하면 기존 데이터베이스 유지 관리 작업이 대부분 필요 없어지므로 운영 오버헤드가 줄어듭니다.

**수동 유지 관리 불필요**  
Aurora DSQL은 스토리지 최적화, 통계 수집 및 성능 튜닝을 자동으로 관리합니다. `VACUUM`과 같은 기존 유지 관리 명령은 시스템에서 처리합니다.  
**이점:** 데이터베이스 유지 관리 기간, vacuum 예약 및 시스템 파라미터 튜닝이 필요 없어집니다.

**자동 파티셔닝 및 규모 조정**  
Aurora DSQL은 액세스 패턴에 따라 데이터를 자동으로 파티셔닝하고 배포합니다. 최적의 배포를 위해 UUID 또는 애플리케이션 생성 ID를 사용합니다.  
**마이그레이션 팁:** 수동 파티셔닝 로직을 제거하고 Aurora DSQL이 데이터 배포를 처리하도록 하세요. 최적의 배포를 위해 UUID 또는 애플리케이션 생성 ID를 사용합니다. 애플리케이션에 순차적 식별자가 필요한 경우 [시퀀스 및 자격 증명 열](sequences-identity-columns.md) 섹션을 참조하세요.

# AI 도구를 사용한 에이전틱 마이그레이션
<a name="dsql-agentic-migration"></a>

AI 코딩 에이전트는 기본 제공 안전 검사를 통해 스키마를 분석하고, 코드를 변환하고, DDL 마이그레이션을 실행하여 Aurora DSQL로의 마이그레이션을 가속화할 수 있습니다.

## 마이그레이션에 Kiro 사용
<a name="dsql-kiro-migration"></a>

[Kiro](https://kiro.dev/)와 같은 코딩 에이전트는 PostgreSQL 코드를 분석하고 Aurora DSQL로 마이그레이션하는 데 도움이 될 수 있습니다.
+ **스키마 분석:** 기존 스키마 파일을 업로드하고 Kiro에게 잠재적 호환성 문제를 식별하고 대안을 제안하도록 요청하세요.
+ **코드 변환:** 애플리케이션 코드를 제공하고 Kiro에게 트리거 로직을 리팩터링하거나, 시퀀스를 UUID로 대체하거나, 트랜잭션 패턴을 수정하도록 요청하세요.
+ **마이그레이션 계획:** Kiro에게 특정 애플리케이션 아키텍처를 기반으로 단계별 마이그레이션 계획을 생성하도록 요청하세요.
+ **DDL 마이그레이션:** 기본 제공 안전 검사 및 사용자 확인과 함께 테이블 다시 만들기 패턴을 사용하여 스키마 수정 실행

**프롬프트 예제:**

```
"Analyze this PostgreSQL schema for DSQL compatibility and suggest alternatives for any unsupported features"

"Help me refactor this trigger function into application-level logic for DSQL migration"

"Create a migration checklist for moving my Django application from PostgreSQL to DSQL"

"Drop the legacy_status column from the orders table"

"Change the price column from VARCHAR to DECIMAL in the products table"
```

## 테이블 다시 만들기를 사용한 DDL 마이그레이션
<a name="dsql-ddl-migration-pattern"></a>

Aurora DSQL MCP 서버에서 AI 에이전트를 사용하는 경우, 특정 ALTER TABLE 작업은 데이터를 안전하게 마이그레이션하는 *테이블 다시 만들기 패턴*을 사용합니다. 에이전트는 각 단계에서 정보를 계속 제공하면서 복잡성을 처리합니다.

다음 작업은 테이블 다시 만들기 패턴을 사용합니다.


| 연산 | 접근 방식 | 
| --- | --- | 
| DROP COLUMN | 새 테이블에서 열 제외 | 
| ALTER COLUMN TYPE | 마이그레이션 중 데이터 유형 캐스팅 | 
| ALTER COLUMN SET/DROP NOT NULL | 새 테이블 정의의 제약 조건 변경 | 
| ALTER COLUMN SET/DROP DEFAULT | 새 테이블 정의에서 기본값 정의 | 
| ADD/DROP CONSTRAINT | 새 테이블에 제약 포함 또는 제거 | 
| MODIFY PRIMARY KEY | 고유성 검증을 사용하여 새 PK 정의 | 
| 열 분할/병합 | SPLIT\$1PART, SUBSTRING 또는 CONCAT 사용 | 

다음 ALTER TABLE 작업은 테이블 다시 만들기 없이 직접 지원됩니다.
+ `ALTER TABLE ... RENAME COLUMN` – 열 이름 바꾸기
+ `ALTER TABLE ... RENAME TO` – 테이블 이름 바꾸기
+ `ALTER TABLE ... ADD COLUMN` – 새 열 추가

**안전 기능:** DDL 마이그레이션을 실행할 때 AI 에이전트는 마이그레이션 계획을 제시하고, 데이터 호환성을 확인하고, 행 수를 확인하고, DROP TABLE과 같은 파괴적인 작업을 수행하기 전에 명시적 승인을 요청합니다.

**배치 마이그레이션**: 행이 3,000개를 초과하는 테이블의 경우 에이전트는 트랜잭션 한도 내에서 유지되도록 500\$11,000개의 행 증분으로 마이그레이션을 자동으로 배치화합니다.

## Aurora DSQL MCP 서버
<a name="dsql-mcp-tools"></a>

Aurora DSQL Model Context Protocol(MCP) 서버를 사용하면 AI 어시스턴트가 Aurora DSQL 클러스터에 직접 연결하고 Aurora DSQL 설명서를 검색할 수 있습니다. 이를 통해 AI는 다음을 수행할 수 있습니다.
+ 기존 스키마 분석 및 마이그레이션 변경 사항 제안
+ 테이블 다시 만들기 패턴을 사용하여 DDL 마이그레이션 실행
+ 마이그레이션 중 쿼리 테스트 및 호환성 확인
+ 최신 Aurora DSQL 설명서를 기반으로 정확한 최신 지침 제공

 Aurora DSQL MCP 서버를 AI 어시스턴트와 함께 사용하려면 [Aurora DSQL MCP 서버](SECTION_aurora-dsql-mcp-server.md)의 설정 지침을 참조하세요.

## PostgreSQL 호환성을 위한 Aurora DSQL 고려 사항
<a name="working-with-postgresql-compatibility-unsupported-limitations"></a>

Aurora DSQL은 분산 아키텍처, 서버리스 운영 및 자동 규모 조정을 가능하게 하는 기능 지원 측면에서 자체 관리형 PostgreSQL과 차이가 있습니다. 대부분의 애플리케이션은 이러한 차이점에도 불구하고 수정 없이 작동합니다.

일반적인 고려 사항은 [Amazon Aurora DSQL 사용에 대한 고려 사항](considerations.md) 섹션을 참조하세요. 할당량 및 한도는 [Amazon Aurora DSQL의 클러스터 할당량 및 데이터베이스 한도](CHAP_quotas.md) 섹션을 참조하세요.
+ Aurora DSQL은 클러스터당 `postgres`라는 단일 내장 데이터베이스를 사용합니다. 논리적 분리를 위해 별도의 Aurora DSQL 클러스터를 만들거나 단일 클러스터 내에서 스키마를 사용합니다.
+ `postgres` 데이터베이스는 광범위한 국제 문자 지원을 제공하는 UTF-8 문자 인코딩을 사용합니다.
+ 데이터베이스는 `C` 데이터 정렬만 사용합니다.
+ Aurora DSQL은 `UTC`를 시스템 시간대로 사용합니다. Postgres는 모든 시간대 인식 날짜 및 시간을 UTC로 내부적으로 저장합니다. `TimeZone` 구성 파라미터를 설정하여 클라이언트에 표시되는 방식을 변환하고 서버가 UTC로 내부적으로 변환하는 데 사용할 클라이언트 입력의 기본값으로 사용할 수 있습니다.
+ 트랜잭션 격리 수준은 PostgreSQL `Repeatable Read`에서 고정됩니다.
+ 트랜잭션의 제약 조건은 다음과 같습니다.
  + DDL 및 DML 작업에는 별도의 트랜잭션이 필요합니다.
  + 하나의 트랜잭션에는 DDL 문이 하나만 포함될 수 있습니다.
  + 하나의 트랜잭션은 보조 인덱스 수와 관계없이 최대 3,000개의 행을 수정할 수 있습니다.
  + 행 3,000개 한도는 모든 DML 문(`INSERT`, `UPDATE`, `DELETE`)에 적용됩니다.
+ 데이터베이스 연결은 1시간 후에 시간 초과됩니다.
+ Aurora DSQL은 스키마 수준 권한 부여를 통해 권한을 관리합니다. 관리자 사용자는 `CREATE SCHEMA`를 사용하여 스키마를 만들고 `GRANT USAGE ON SCHEMA`를 사용하여 액세스 권한을 부여합니다. 관리자 사용자는 퍼블릭 스키마에서 객체를 관리하는 반면, 관리자가 아닌 사용자는 명확한 소유권 경계를 위해 사용자가 만든 스키마에서 객체를 만듭니다. 자세한 내용은 [데이터베이스 역할이 데이터베이스에서 SQL을 사용하도록 권한 부여](using-database-and-iam-roles.md#using-database-and-iam-roles-custom-database-roles-sql) 섹션을 참조하세요.

## 마이그레이션에 도움이 필요하세요?
<a name="dsql-migration-feedback-link"></a>

마이그레이션에 중요하지만 현재 Aurora DSQL에서 지원되지 않는 기능이 있는 경우 [Amazon Aurora DSQL에 대한 피드백 제공](providing-feedback.md)에서 AWS와 피드백을 공유하는 방법에 대한 정보를 참조하세요.

# Aurora DSQL의 동시성 제어
<a name="working-with-concurrency-control"></a>

동시성을 통해 여러 세션이 데이터 무결성과 일관성을 손상시키지 않고 동시에 데이터에 액세스하고 수정할 수 있습니다. Aurora DSQL은 현대적 비잠금 동시성 제어 메커니즘을 구현하면서 [PostgreSQL 호환성](https://docs.aws.amazon.com/aurora-dsql/latest/userguide/working-with-postgresql-compatibility.html)을 제공합니다. 스냅샷 격리를 통해 완전한 ACID 규정 준수를 유지하여 데이터 일관성과 신뢰성을 보장합니다.

Aurora DSQL의 주요 이점은 일반적인 데이터베이스 성능 병목 현상을 제거하는 비잠금 아키텍처라는 점입니다. Aurora DSQL은 느린 트랜잭션이 다른 작업을 차단하는 것을 방지하고 교착 상태의 위험을 제거합니다. 이 접근 방식을 통해 Aurora DSQL은 성능과 확장성이 필수인 처리량이 많은 애플리케이션에 특히 유용합니다.

## 트랜잭션 충돌
<a name="dsql-transaction-conflicts"></a>

Aurora DSQL은 기존 잠금 기반 시스템과 다르게 작동하는 낙관적 동시성 제어(OCC)를 사용합니다. OCC는 잠금을 사용하는 대신 커밋 시 충돌을 평가합니다. 동일한 행을 업데이트하는 동안 여러 트랜잭션이 충돌하는 경우 Aurora DSQL은 다음과 같이 트랜잭션을 관리합니다.
+ 커밋 시간이 가장 빠른 트랜잭션은 Aurora DSQL에서 처리됩니다.
+ 충돌하는 트랜잭션에 PostgreSQL 직렬화 오류가 수신되어 재시도해야 함을 나타냅니다.

충돌을 처리하기 위해 재시도 로직을 구현하도록 애플리케이션을 설계하세요. 이상적인 설계 패턴은 멱등적이므로 가능하면 트랜잭션 재시도를 첫 번째 수단으로 사용할 수 있습니다. 권장 로직은 표준 PostgreSQL 잠금 제한 시간 또는 교착 상태의 중단 및 재시도 로직과 유사합니다. 그러나 OCC에서는 애플리케이션이 이 로직을 더 자주 실행해야 합니다.

## 트랜잭션 성능 최적화 지침
<a name="dsql-perf-guidelines"></a>

성능을 최적화하려면 단일 키 또는 작은 키 범위에서 높은 경합을 최소화합니다. 이 목표를 달성하려면 다음 지침에 따라 클러스터 키 범위에 업데이트를 분산하도록 스키마를 설계하세요.
+ 테이블에 대한 임의 프라이머리 키를 선택합니다.
+ 단일 키에 대한 경합을 높이는 패턴을 피합니다. 이 접근 방식은 트랜잭션 볼륨이 증가하더라도 최적의 성능을 보장합니다.

# Aurora DSQL의 DDL 및 분산 트랜잭션
<a name="working-with-ddl"></a>

데이터 정의 언어(DDL)는 Aurora DSQL에서 PostgreSQL과 다르게 작동합니다. Aurora DSQL에는 다중 테넌트 컴퓨팅 및 스토리지 플릿을 기반으로 구축된 다중 AZ 분산 및 비공유 데이터베이스 계층이 있습니다. 단일 프라이머리 데이터베이스 노드 또는 리더가 없으므로 데이터베이스 카탈로그가 배포됩니다. 따라서 Aurora DSQL은 DDL 스키마 변경을 분산 트랜잭션으로 관리합니다.

특히 DDL은 Aurora DSQL에서 다음과 같이 다르게 작동합니다.

**동시성 제어 오류**  
Aurora DSQL은 다른 트랜잭션이 리소스를 업데이트하는 동안 한 트랜잭션을 실행하는 경우 동시성 제어 위반 오류를 반환합니다. 예를 들어 다음과 같은 일련의 작업을 고려합니다.  

1. 세션 1에서 사용자는 `mytable` 테이블에 열을 추가합니다.

1. 세션 2에서 사용자는 `mytable`에 행을 삽입하려고 시도합니다.

   Aurora DSQL에서 `SQL Error [40001]: ERROR: schema has been updated by another transaction, please retry: (OC001).` 오류를 반환합니다.

**동일한 트랜잭션의 DDL 및 DML**  
Aurora DSQL의 트랜잭션은 하나의 DDL 문만 포함할 수 있으며 DDL 문과 DML 문을 모두 가질 수는 없습니다. 이 제한은 테이블을 생성하고 동일한 트랜잭션 내에서 동일한 테이블에 데이터를 삽입할 수 없음을 의미합니다. 예를 들어 Aurora DSQL은 다음과 같은 순차 트랜잭션을 지원합니다.  

```
BEGIN;
  CREATE TABLE mytable (ID_col integer);
COMMIT;

BEGIN;
  INSERT into FOO VALUES (1);
COMMIT;
```
Aurora DSQL은 `CREATE` 및 `INSERT` 문을 모두 포함하는 다음 트랜잭션을 지원하지 않습니다.  

```
BEGIN;
  CREATE TABLE FOO (ID_col integer);
  INSERT into FOO VALUES (1);
COMMIT;
```

**비동기 DDL**  
표준 PostgreSQL에서 `CREATE INDEX`와 같은 DDL 작업은 영향을 받는 테이블을 잠그므로 다른 세션의 읽기 및 쓰기에 사용할 수 없습니다. Aurora DSQL에서 이러한 DDL 문은 백그라운드 관리자를 사용하여 비동기적으로 실행됩니다. 영향을 받는 테이블에 대한 액세스는 차단되지 않습니다. 따라서 대규모 테이블의 DDL은 가동 중지 시간이나 성능 영향 없이 실행할 수 있습니다. Aurora DSQL의 비동기 작업 관리자에 대한 자세한 내용은 [Aurora DSQL의 비동기 인덱스](working-with-create-index-async.md) 섹션을 참조하세요.

# Aurora DSQL의 프라이머리 키
<a name="working-with-primary-keys"></a>

Aurora DSQL에서 프라이머리 키는 테이블 데이터를 물리적으로 구성하는 기능입니다. PostgreSQL의 `CLUSTER` 작업 또는 다른 데이터베이스의 클러스터링된 인덱스와 유사합니다. 프라이머리 키를 정의하면 Aurora DSQL은 테이블의 모든 열을 포함하는 인덱스를 생성합니다. Aurora DSQL의 프라이머리 키 구조는 효율적인 데이터 액세스 및 관리를 보장합니다.

## 데이터 구조 및 스토리지
<a name="dsql-primary-key-storage"></a>

프라이머리 키를 정의하면 Aurora DSQL은 프라이머리 키 순서로 테이블 데이터를 저장합니다. 이 인덱스 구성 구조를 사용하면 프라이머리 키 조회가 기존 B-트리 인덱스에서처럼 데이터에 대한 포인터를 따르는 대신 모든 열 값을 직접 검색할 수 있습니다. 데이터를 한 번만 재구성하는 PostgreSQL의 `CLUSTER` 작업과 달리 Aurora DSQL은 이 순서를 자동으로 지속적으로 유지합니다. 이 접근 방식은 프라이머리 키 액세스에 의존하는 쿼리의 성능을 개선합니다.

또한 Aurora DSQL은 프라이머리 키를 사용하여 테이블 및 인덱스의 각 행에 대한 클러스터 전체 고유 키를 생성합니다. 이 고유 키는 분산 데이터 관리도 뒷받침합니다. 이를 통해 여러 노드에서 데이터를 자동으로 파티셔닝하여 확장 가능한 스토리지와 높은 동시성을 지원할 수 있습니다. 따라서 프라이머리 키 구조는 Aurora DSQL이 자동으로 규모 조정되고 동시 워크로드를 효율적으로 관리하는 데 도움이 됩니다.

## 프라이머리 키 선택 지침
<a name="dsql-primary-key-guidelines"></a>

Aurora DSQL에서 프라이머리 키를 선택하고 사용할 때는 다음 지침을 고려하세요.
+ 테이블을 생성할 때 프라이머리 키를 정의합니다. 나중에 이 키를 변경하거나 새 프라이머리 키를 추가할 수 없습니다. 프라이머리 키는 데이터 파티셔닝 및 쓰기 처리량의 자동 규모 조정에 사용되는 클러스터 전체 키의 일부가 됩니다. 프라이머리 키를 지정하지 않으면 Aurora DSQL이 합성 숨김 ID를 할당합니다.
+ 쓰기 볼륨이 많은 테이블의 경우 단조롭게 증가하는 정수를 프라이머리 키로 사용하지 마세요. 그럴 경우 모든 새 삽입을 단일 파티션으로 전달하여 성능 문제가 발생할 수 있습니다. 대신 임의의 분산이 있는 프라이머리 키를 사용하여 스토리지 파티션 간에 쓰기를 고르게 분산할 수 있습니다.
+ 자주 변경되지 않거나 읽기 전용인 테이블의 경우 오름차순 키를 사용할 수 있습니다. 오름차순 키의 예로는 타임스탬프 또는 시퀀스 번호가 있습니다. 밀집 키에는 밀접하게 이격되거나 중복된 값이 많습니다. 쓰기 성능이 덜 중요하기 때문에 밀도가 높더라도 오름차순 키를 사용할 수 있습니다.
+ 전체 테이블 스캔이 성능 요구 사항을 충족하지 않는 경우 더 효율적인 액세스 방법을 선택합니다. 대부분의 경우 이는 쿼리에서 가장 일반적인 조인 및 조회 키와 일치하는 프라이머리 키를 사용하는 것을 의미합니다.
+ 프라이머리 키에 있는 열의 최대 결합 크기는 1KiB입니다. 자세한 내용은 [Aurora DSQL의 데이터베이스 한도](https://docs.aws.amazon.com/aurora-dsql/latest/userguide/CHAP_quotas.html#SECTION_database-limits) 및 [Aurora DSQL에서 지원되는 데이터 유형](https://docs.aws.amazon.com/aurora-dsql/latest/userguide/working-with-postgresql-compatibility-supported-data-types)을 참조하세요.
+ 프라이머리 키 또는 보조 인덱스에 최대 8개의 열을 포함할 수 있습니다. 자세한 내용은 [Aurora DSQL의 데이터베이스 한도](https://docs.aws.amazon.com/aurora-dsql/latest/userguide/CHAP_quotas.html#SECTION_database-limits) 및 [Aurora DSQL에서 지원되는 데이터 유형](https://docs.aws.amazon.com/aurora-dsql/latest/userguide/working-with-postgresql-compatibility-supported-data-types)을 참조하세요.

# 시퀀스 및 자격 증명 열
<a name="sequences-identity-columns"></a>

시퀀스 및 자격 증명 열은 정수 값을 생성하며 간단하거나 사람이 읽을 수 있는 식별자가 필요할 때 유용합니다. 이러한 값에는 [`CREATE SEQUENCE`](create-sequence-syntax-support.md) 설명서에 설명된 할당 및 캐싱 동작이 포함됩니다.

**Topics**
+ [시퀀스 조작 함수](sequence-functions-syntax-support.md)
+ [ID 열](sequences-identity-columns-overview.md)
+ [시퀀스 및 자격 증명 열 작업](sequences-identity-columns-working-with.md)

# 시퀀스 조작 함수
<a name="sequence-functions-syntax-support"></a>

이 섹션에서는 시퀀스 객체(시퀀스 생성기 또는 단순히 시퀀스라고도 함)를 조작하기 위한 함수에 대해 설명합니다. 시퀀스 객체는 [`CREATE SEQUENCE`](create-sequence-syntax-support.md)로 만들어진 특수 단일 행 테이블입니다. 시퀀스 객체는 일반적으로 테이블 행의 고유 식별자를 생성하는 데 사용됩니다. 시퀀스 함수는 시퀀스 객체에서 연속 시퀀스 값을 얻기 위한 간단한 다중 사용자 환경에서 안전한 방법을 제공합니다.

**중요**  
시퀀스를 사용할 때는 캐시 값을 신중하게 고려해야 합니다. 자세한 내용은 [`CREATE SEQUENCE`](create-sequence-syntax-support.md) 페이지의 중요 안내를 참조하세요.  
워크로드 패턴을 기반으로 시퀀스를 가장 잘 사용하는 방법에 대한 지침은 [시퀀스 및 자격 증명 열 작업](sequences-identity-columns-working-with.md) 섹션을 참조하세요.


| 함수 | 설명 | 
| --- | --- | 
| nextval ( regclass ) → bigint | 시퀀스 객체를 다음 값으로 진행시키고 해당 값을 반환합니다. 이 작업은 원자적으로 수행됩니다. 여러 nextval 세션이 동시에 실행되더라도 각 세션은 안전하게 서로 다른 시퀀스 값을 수신합니다. 시퀀스 객체가 기본 파라미터로 만들어진 경우 연속 nextval 직접 호출은 1로 시작하는 증가하는 값을 반환합니다. [`CREATE SEQUENCE`](create-sequence-syntax-support.md) 명령에서 적절한 파라미터를 사용하여 다른 동작을 가져올 수 있습니다. 이 함수에는 시퀀스에 대한 USAGE 또는 UPDATE 권한이 필요합니다. | 
| setval ( regclass, bigint [, boolean ] ) → bigint | 시퀀스 객체의 현재 값과 선택적으로 is\$1called 플래그를 설정합니다. 2-파라미터 형식은 시퀀스의 last\$1value 필드를 지정된 값으로 설정하고 해당 is\$1called 필드를 true로 설정합니다. 즉, 다음 nextval은 값을 반환하기 전에 시퀀스를 진행합니다. currval에서 보고할 값도 지정된 값으로 설정됩니다. 3-파라미터 양식에서는 is\$1called를 true 또는 false로 설정할 수 있습니다. true는 2-파라미터 양식과 동일한 효과를 갖습니다. false로 설정하면 다음 nextval은 지정된 값을 정확히 반환하고 시퀀스 진행은 다음 nextval로 시작됩니다. 또한 currval에서 보고하는 값은 여기에서 변경되지 않습니다. 예제: <pre>SELECT setval('myseq', 42);           -- Next nextval will return 43<br />SELECT setval('myseq', 42, true);     -- Same as above<br />SELECT setval('myseq', 42, false);    -- Next nextval will return 42</pre> setval에서 반환되는 결과는 두 번째 인수의 값일 뿐입니다. 이 함수에는 시퀀스에 대한 UPDATE 권한이 필요합니다. | 
| currval ( regclass ) → bigint | 현재 세션에서 이 시퀀스에 대해 nextval에서 가장 최근에 얻은 값을 반환합니다. (이 세션에서 이 시퀀스에 대해 nextval이 직접적으로 호출된 적이 없는 경우 오류가 보고됩니다.) 세션-로컬 값을 반환하기 때문에 현재 세션으로 인해 다른 세션이 nextval을 실행했는지 여부에 대한 예측 가능한 답변을 제공합니다. 이 함수에는 시퀀스에 대한 USAGE 또는 SELECT 권한이 필요합니다. | 
| lastval () → bigint | 현재 트랜잭션에서 nextval이 가장 최근에 반환한 값을 반환합니다. 이 함수는 시퀀스 이름을 인수로 취하는 대신 현재 트랜잭션에서 nextval이 가장 최근에 적용된 시퀀스를 참조한다는 점을 제외하면 currval과 동일합니다. nextval이 현재 트랜잭션에서 아직 직접적으로 호출되지 않은 경우 lastval을 직접적으로 호출하는 것은 오류입니다. 이 함수에는 마지막으로 사용된 시퀀스에 대한 USAGE 또는 SELECT 권한이 필요합니다. | 

**주의**  
직접 호출 트랜잭션이 나중에 중단되는 경우 `nextval`에서 얻은 값은 재사용을 위해 회수되지 않습니다. 즉, 트랜잭션 중단 또는 데이터베이스 충돌로 인해 할당된 값 시퀀스에 공백이 발생할 수 있습니다. 이는 트랜잭션 중단 없이도 발생할 수 있습니다. 예를 들어 `ON CONFLICT` 절이 있는 `INSERT`는 `ON CONFLICT` 규칙을 대신 따르게 하는 충돌을 감지하기 전에 필요한 `nextval` 직접 호출 수행을 포함하여 삽입할 튜플을 계산합니다. 따라서 Aurora DSQL의 시퀀스 객체는 *‘간격 없는’ 시퀀스를 얻는 데 사용할 수 없습니다*.  
마찬가지로 `setval`에서 수행한 시퀀스 상태 변경은 다른 트랜잭션에 즉시 표시되며 호출 트랜잭션이 롤백되는 경우 실행 취소되지 않습니다.

시퀀스 함수에 의해 작동할 시퀀스는 `regclass` 인수에 의해 지정됩니다. 인수는 단순히 `pg_class` 시스템 카탈로그에 있는 시퀀스의 OID입니다. 그러나 `regclass` 데이터 형식의 입력 변환기가 작업을 대신 수행하므로 OID를 직접 조회할 필요는 없습니다. 자세한 내용은 [객체 식별자 유형](https://www.postgresql.org/docs/current/datatype-oid.html)에 대한 PostgreSQL 설명서를 참조하세요.

# ID 열
<a name="sequences-identity-columns-overview"></a>

**중요**  
자격 증명 열을 사용할 때는 캐시 값을 신중하게 고려해야 합니다. 자세한 내용은 [`CREATE SEQUENCE`](create-sequence-syntax-support.md) 페이지의 중요 안내를 참조하세요.  
워크로드 패턴을 기반으로 자격 증명 열을 가장 잘 사용하는 방법에 대한 지침은 [시퀀스 및 자격 증명 열 작업](sequences-identity-columns-working-with.md) 섹션을 참조하세요.

자격 증명 열은 암시적 시퀀스에서 자동으로 생성되는 특수 열입니다. 키 값을 생성하는 데 사용할 수 있습니다. 자격 증명 열을 만들려면 [`CREATE TABLE`](create-table-syntax-support.md)의 `GENERATED ... AS IDENTITY` 절을 사용합니다. 예를 들면 다음과 같습니다.

```
CREATE TABLE people (
    id bigint GENERATED ALWAYS AS IDENTITY (CACHE 70000),
    ...
);
```

또는 다음을 사용합니다.

```
CREATE TABLE people (
    id bigint GENERATED BY DEFAULT AS IDENTITY (CACHE 70000),
    ...
);
```

자세한 내용은 [`CREATE TABLE`](create-table-syntax-support.md) 섹션을 참조하세요.

자격 증명 열이 있는 테이블에서 `INSERT` 명령이 실행되고 자격 증명 열에 명시적으로 지정된 값이 없는 경우 암시적 시퀀스에서 생성된 값이 삽입됩니다. 예를 들어 앞의 정의를 사용하고 적절한 열을 추가로 가정하여 다음을 작성합니다.

```
INSERT INTO people (name, address) VALUES ('A', 'foo');
INSERT INTO people (name, address) VALUES ('B', 'bar');
```

1부터 `id` 열 값을 생성하여 다음 테이블 데이터를 생성합니다.

```
 id | name | address
----+------+---------
  1 | A    | foo
  2 | B    | bar
```

또는 값 대신 `DEFAULT` 키워드를 지정하여 시퀀스 생성 값을 명시적으로 요청할 수 있습니다.

```
INSERT INTO people (id, name, address) VALUES (DEFAULT, 'C', 'baz');
```

마찬가지로 `DEFAULT` 키워드는 `UPDATE` 명령에 사용할 수 있습니다.

따라서 여러 가지 면에서 자격 증명 열은 기본값이 있는 열처럼 동작합니다.

열 정의의 `ALWAYS` 및 `BY DEFAULT` 절은 `INSERT` 및 `UPDATE` 명령에서 사용자 지정 값을 명시적으로 처리하는 방법을 결정합니다. `INSERT` 명령에서 `ALWAYS`가 선택된 경우 `INSERT` 문이 `OVERRIDING SYSTEM VALUE`를 지정하는 경우에만 사용자 지정 값이 허용됩니다. `BY DEFAULT`를 선택하면 사용자 지정 값이 우선합니다. 따라서 `BY DEFAULT`를 사용하면 기본값과 더 유사한 동작이 발생하며, 기본값은 명시적 값으로 재정의될 수 있는 반면 `ALWAYS`는 실수로 명시적 값을 삽입하는 것에 대해 더 많은 보호를 제공합니다.

자격 증명 열의 데이터 형식은 시퀀스에서 지원하는 데이터 형식 중 하나여야 합니다. ([`CREATE SEQUENCE`](create-sequence-syntax-support.md)를 참조하세요.) 자격 증명 열을 만들 때 연결된 시퀀스의 속성을 지정하거나([`CREATE TABLE`](create-table-syntax-support.md) 참조) 나중에 변경할 수 있습니다([`ALTER TABLE`](alter-table-syntax-support.md) 참조).

자격 증명 열은 자동으로 `NOT NULL`로 표시됩니다. 그러나 자격 증명 열은 고유성을 보장하지 않습니다. (시퀀스는 일반적으로 고유한 값을 반환하지만 앞서 설명한 대로 시퀀스를 재설정하거나 값을 자격 증명 열에 수동으로 삽입할 수 있습니다.) `PRIMARY KEY` 또는 `UNIQUE` 제약 조건을 사용하여 고유성을 적용해야 합니다.

# 시퀀스 및 자격 증명 열 작업
<a name="sequences-identity-columns-working-with"></a>

이 섹션에서는 워크로드 패턴을 기반으로 시퀀스 및 자격 증명 열을 가장 잘 사용하는 방법을 이해하는 데 도움이 됩니다.

**중요**  
할당 및 캐싱 동작에 대한 자세한 내용은 [`CREATE SEQUENCE`](create-sequence-syntax-support.md) 페이지의 중요 안내를 참조하세요.

## 식별자 유형 선택
<a name="sequences-identity-columns-choosing-identifier-types"></a>

Amazon Aurora DSQL은 시퀀스 또는 자격 증명 열을 사용하여 생성된 UUID 기반 식별자와 정수 값을 모두 지원합니다. 이러한 옵션은 값이 할당되는 방식과 로드 시 조정되는 방식에 따라 다릅니다.

UUID 값은 조정 없이 만들 수 있으며 식별자가 자주 또는 여러 세션에서 만들어지는 워크로드에 적합합니다. Amazon Aurora DSQL은 분산 작업을 위해 설계되었으므로 조정을 피하는 것이 유용한 경우가 많습니다. 따라서 UUID 기본 식별자 유형으로 권장되며, 특히 확장성이 중요하고 식별자의 엄격한 순서 지정이 필요하지 않은 워크로드의 프라이머리 키에 권장됩니다.

시퀀스 및 자격 증명 열은 사람이 읽을 수 있는 식별자, 보고 및 외부 인터페이스에 편리한 작은 정수 값을 생성합니다. 사용성 또는 통합 이유로 숫자 식별자를 선호하는 경우, UUID 기반 식별자와 함께 시퀀스 또는 자격 증명 열을 사용하는 것이 좋습니다. 정수 시퀀스 또는 자격 증명 값이 필요한 경우, 적절한 캐시 크기를 선택하는 것이 워크로드 설계의 중요한 부분이 됩니다. 캐시 크기 선택에 대한 지침은 다음 섹션을 참조하세요.

## 캐시 크기 선택
<a name="sequences-identity-columns-choosing-cache-size"></a>

적절한 캐시 값을 선택하는 것은 시퀀스 및 자격 증명 열을 효과적으로 사용하는 데 중요한 부분입니다. 캐시 설정은 로드 시 식별자 할당이 작동하는 방식을 결정하여 시스템 처리량과 값이 할당 순서를 반영하는 정도에 영향을 미칩니다.

**`CACHE >= 65536`의 캐시 크기가 클수록 다음과 같은 경우에 적합합니다.**
+ 식별자가 높은 빈도로 생성됨
+ 여러 세션이 동시에 삽입됨
+ 워크로드가 간격과 눈에 보이는 순서 지정 효과를 허용할 수 있음

예를 들어 대용량 이벤트 수집 워크로드(예: IoT 또는 원격 측정)와 작업 실행 ID, 지원 사례 참조 또는 내부 주문 번호와 같은 운영 식별자는 일반적으로 식별자가 자주 생성되고 엄격한 순서 지정이 필요하지 않은 더 큰 캐시 크기의 이점을 누릴 수 있습니다.

**다음과 같은 경우에는 캐시 크기 1이 더 적합합니다.**
+ 할당률이 비교적 낮음
+ 식별자가 시간이 지남에 따라 할당 순서를 더 가깝게 따를 것으로 예상됨
+ 간격을 최소화하는 것이 최대 처리량보다 더 중요함

식별자가 덜 자주 생성되고 순서 지정이 더 가까운 계정 또는 참조 번호 할당과 같은 워크로드에는 캐시 크기 1이 더 적합합니다.

# Aurora DSQL의 비동기 인덱스
<a name="working-with-create-index-async"></a>

`CREATE INDEX ASYNC` 명령은 지정된 테이블의 하나 이상의 열에 인덱스를 생성합니다. 이 명령은 다른 트랜잭션을 차단하지 않는 비동기 DDL 작업입니다. `CREATE INDEX ASYNC`를 실행하면 Aurora DSQL이 즉시 `job_id`를 반환합니다.

`sys.jobs` 시스템 뷰를 사용하여 이 비동기 작업의 상태를 모니터링할 수 있습니다. 인덱스 생성 작업이 진행 중일 때 다음 절차와 명령을 사용할 수 있습니다.

**`sys.wait_for_job(job_id)'your_index_creation_job_id'`**  
지정된 작업이 완료되거나 실패할 때까지 현재 세션을 차단합니다. 성공 또는 실패를 나타내는 부울 값을 반환합니다.

**`DROP INDEX`**  
진행 중인 인덱스 빌드 작업을 취소합니다.  
비동기 인덱스 생성이 완료되면 Aurora DSQL은 시스템 카탈로그를 업데이트하여 인덱스를 활성으로 표시합니다.  
 이 업데이트 중에 동일한 네임스페이스의 객체에 액세스하는 동시 트랜잭션에는 동시성 오류가 발생할 수 있습니다.

Aurora DSQL이 비동기 인덱스 작업을 완료하면 시스템 카탈로그를 업데이트하여 인덱스가 활성 상태임을 표시합니다. 현재 다른 트랜잭션이 동일한 네임스페이스의 객체를 참조하는 경우 동시성 오류가 표시될 수 있습니다.

## 구문
<a name="working-with-create-index-syntax"></a>

`CREATE INDEX ASYNC`는 다음 구문을 사용합니다.

```
CREATE [ UNIQUE ] INDEX ASYNC [ IF NOT EXISTS ] name ON table_name 
     ( { column_name } [ NULLS { FIRST | LAST } ] ) 
     [ INCLUDE ( column_name [, ...] ) ] 
     [ NULLS [ NOT ] DISTINCT ]
```

## 파라미터
<a name="working-with-create-index-parameters"></a>

**`UNIQUE`**  
인덱스를 생성할 때와 데이터를 추가할 때마다 테이블에 중복 값이 있는지 확인하도록 Aurora DSQL에 알립니다. 이 파라미터를 지정하는 경우 중복 항목이 발생하는 작업을 삽입 및 업데이트하면 오류가 발생합니다.

**`IF NOT EXISTS`**  
동일한 이름의 인덱스가 이미 있는 경우 Aurora DSQL에서 예외가 발생하지 않아야 함을 나타냅니다. 이 경우 Aurora DSQL은 새 인덱스를 생성하지 않습니다. 생성하려는 인덱스는 존재하는 인덱스와 구조가 매우 다를 수 있습니다. 이 파라미터를 지정하면 인덱스 이름이 필요합니다.

**`name`**  
인덱스의 이름입니다. 이 파라미터에는 스키마 이름을 포함할 수 없습니다.  
Aurora DSQL은 상위 테이블과 동일한 스키마에 인덱스를 생성합니다. 인덱스의 이름은 스키마의 테이블 또는 인덱스와 같은 다른 객체의 이름과 달라야 합니다.  
이름을 지정하지 않으면 Aurora DSQL은 상위 테이블 및 인덱싱된 열의 이름을 기반으로 이름을 자동으로 생성합니다. 예를 들어 `CREATE INDEX ASYNC on table1 (col1, col2)`를 실행하면 Aurora DSQL이 인덱스의 이름을 `table1_col1_col2_idx`로 자동으로 지정합니다.

**`NULLS FIRST | LAST`**  
Null 열과 Null이 아닌 열의 정렬 순서입니다. `FIRST`는 Aurora DSQL이 Null이 아닌 열 앞에 Null 열을 정렬해야 함을 나타냅니다. `LAST`는 Aurora DSQL이 Null이 아닌 열 뒤에 Null 열을 정렬해야 함을 나타냅니다.

**`INCLUDE`**  
인덱스에 키가 아닌 열로 포함할 열 목록입니다. 인덱스 스캔 검색 검증에는 키가 아닌 열을 사용할 수 없습니다. Aurora DSQL은 인덱스의 고유성 측면에서 이 열을 무시합니다.

**`NULLS DISTINCT | NULLS NOT DISTINCT`**  
Aurora DSQL이 Null 값을 고유 인덱스에서 구별되는 것으로 간주해야 하는지를 지정합니다. 기본값은 `DISTINCT`입니다. 즉, 고유 인덱스는 열에 여러 Null 값을 포함할 수 있습니다. `NOT DISTINCT`는 인덱스가 열에 여러 Null 값을 포함할 수 없음을 나타냅니다.

## 사용 노트
<a name="working-with-create-index-usage-notes"></a>

다음 지침을 참고하세요.
+ `CREATE INDEX ASYNC` 명령은 잠금을 도입하지 않습니다. 또한 Aurora DSQL이 인덱스를 생성하는 데 사용하는 기본 테이블에도 영향을 주지 않습니다.
+ 스키마 마이그레이션 작업 중에는 `sys.wait_for_job(job_id)'your_index_creation_job_id'` 프로시저가 유용합니다. 이를 통해 후속 DDL 및 DML 작업이 새로 생성된 인덱스를 대상으로 합니다.
+ Aurora DSQL은 새 비동기 작업을 실행할 때마다 `sys.jobs` 뷰를 확인하고 30분 이상 `completed` 또는 `failed` 상태인 작업을 삭제합니다. 따라서 `sys.jobs`은 주로 진행 중인 작업을 표시하고 이전 작업에 대한 정보는 포함하지 않습니다.
+ Aurora DSQL이 비동기 인덱스를 빌드하지 못하면 인덱스는 `INVALID`를 유지합니다. 고유 인덱스의 경우 인덱스를 삭제할 때까지 DML 작업에는 고유성 제약이 적용됩니다. 잘못된 인덱스를 삭제하고 다시 생성하는 것이 좋습니다.

## 인덱스 생성: 예시
<a name="working-with-create-index-example"></a>

다음 예시에서는 스키마, 테이블, 인덱스를 생성하는 방법을 보여줍니다.

1. `test.departments`이라는 테이블을 생성합니다.

   ```
   CREATE SCHEMA test;
   
   CREATE TABLE test.departments (name varchar(255) primary key NOT null, 
        manager varchar(255), 
        size varchar(4));
   ```

1. 테이블에 행을 삽입합니다.

   ```
   INSERT INTO test.departments VALUES ('Human Resources', 'John Doe', '10')
   ```

1. 비동기 인덱스를 생성합니다.

   ```
   CREATE INDEX ASYNC test_index on test.departments(name, manager, size);
   ```

   `CREATE INDEX` 명령은 아래와 같이 작업 ID를 반환합니다.

   ```
   job_id 
   -------------------------- 
   jh2gbtx4mzhgfkbimtgwn5j45y
   ```

   `job_id`는 Aurora DSQL이 인덱스를 생성하기 위해 새 작업을 제출했음을 나타냅니다. `sys.wait_for_job(job_id)'your_index_creation_job_id'` 프로시저를 사용하여 작업이 완료되거나 제한 시간이 초과될 때까지 세션에서 다른 작업을 차단할 수 있습니다.

## 인덱스 생성 상태 쿼리: 예
<a name="dsql-index-status-example"></a>

다음 예시와 같이 `sys.jobs` 시스템 뷰를 쿼리하여 인덱스의 생성 상태를 확인합니다.

```
SELECT * FROM sys.jobs where job_id = 'wqhu6ewifze5xitg3umt24h5ua';
```

Aurora DSQL은 다음과 유사한 응답을 반환합니다.

```
           job_id           |  status   | details |  job_type   | class_id | object_id |    object_name    |       start_time       |      update_time
----------------------------+-----------+---------+-------------+----------+-----------+-------------------+------------------------+------------------------
 wqhu6ewifze5xitg3umt24h5ua | completed |         | INDEX_BUILD |     1259 |     26433 | public.nt2_c1_idx | 2025-09-25 22:07:31+00 | 2025-09-25 22:07:46+00
```

상태 열은 다음 값 중 하나일 수 있습니다.


| Status | 설명 | 
| --- | --- | 
| submitted | 작업이 제출되었지만 Aurora DSQL에서 아직 처리를 시작하지 않았습니다. | 
| processing | Aurora DSQL이 작업을 처리하고 있습니다. | 
| failed | 작업이 실패했습니다. 자세한 내용은 세부 정보 열을 확인하세요. Aurora DSQL이 인덱스를 빌드하지 못한 경우 Aurora DSQL은 인덱스 정의를 자동으로 제거하지 않습니다. DROP INDEX 명령을 사용하여 인덱스를 수동으로 제거해야 합니다. | 
| completed | Aurora DSQL이 작업을 성공적으로 완료했습니다. | 

카탈로그 테이블 `pg_index` 및 `pg_class`를 통해 인덱스의 상태를 쿼리할 수도 있습니다. 특히 `indisvalid` 및 `indisimmediate` 속성은 인덱스의 상태를 알려줄 수 있습니다. Aurora DSQL이 인덱스를 생성하는 동안 초기 상태는 `INVALID`입니다. 인덱스의 `indisvalid` 플래그는 인덱스가 유효하지 않음을 나타내는 `FALSE` 또는 `f`를 반환합니다. 플래그가 `TRUE` 또는 `t`를 반환하면 인덱스가 준비된 것입니다.

```
SELECT relname AS index_name, indisvalid as is_valid, pg_get_indexdef(indexrelid) AS index_definition
from pg_index, pg_class
WHERE pg_class.oid = indexrelid AND indrelid = 'test.departments'::regclass;
```

```
    index_name    | is_valid |                                                 index_definition                                                  
------------------+----------+-------------------------------------------------------------------------------------------------------------------
 department_pkey  |     t    | CREATE UNIQUE INDEX department_pkey ON test.departments USING btree_index (title) INCLUDE (name, manager, size)
 test_index1      |     t    | CREATE INDEX test_index1 ON test.departments USING btree_index (name, manager, size)
```

## 고유 인덱스 빌드 실패
<a name="unique-index-failures"></a>

비동기 고유 인덱스 빌드 작업에서 `Found duplicate key while validating index for UCVs`라는 세부 정보와 함께 실패 상태가 표시되는 경우 고유성 제약 조건 위반으로 인해 고유 인덱스를 빌드할 수 없음을 나타냅니다.

**고유 인덱스 빌드 실패를 해결하는 방법**

1. 고유한 보조 인덱스에 지정된 키에 대해 중복 항목이 있는 기본 테이블의 행을 제거합니다.

1. 실패한 인덱스를 삭제합니다.

1. 인덱스 생성 명령을 새로 실행합니다.

## 기본 테이블에서 고유성 위반 감지
<a name="detect-uniqueness-violation"></a>

다음 SQL 쿼리는 테이블의 지정된 열에서 중복 값을 식별하는 데 도움이 됩니다. 이는 현재 프라이머리 키로 설정되지 않았거나 사용자 테이블의 이메일 주소와 같은 고유한 제약 조건이 없는 열에 고유성을 적용해야 하는 경우에 특히 유용합니다.

 아래 예시에서는 샘플 사용자 테이블을 생성하고, 알려진 중복이 포함된 테스트 데이터로 채우고, 감지 쿼리를 실행하는 방법을 보여줍니다.

**테이블 스키마 정의**

```
-- Drop the table if it exists
DROP TABLE IF EXISTS users;

-- Create the users table with a simple integer primary key
CREATE TABLE users (
    user_id INTEGER PRIMARY KEY,
    email VARCHAR(255),
    first_name VARCHAR(100),
    last_name VARCHAR(100),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```

**중복 이메일 주소 세트가 포함된 샘플 데이터 삽입**

```
-- Insert sample data with explicit IDs
INSERT INTO users (user_id, email, first_name, last_name) VALUES
    (1, 'john.doe@example.com', 'John', 'Doe'),
    (2, 'jane.smith@example.com', 'Jane', 'Smith'),
    (3, 'john.doe@example.com', 'Johnny', 'Doe'),
    (4, 'alice.wong@example.com', 'Alice', 'Wong'),
    (5, 'bob.jones@example.com', 'Bob', 'Jones'),
    (6, 'alice.wong@example.com', 'Alicia', 'Wong'),
    (7, 'bob.jones@example.com', 'Robert', 'Jones');
```

**중복 탐지 쿼리 실행**

```
-- Query to find duplicates
WITH duplicates AS (
    SELECT email, COUNT(*) as duplicate_count
    FROM users
    GROUP BY email
    HAVING COUNT(*) > 1
)
SELECT u.*, d.duplicate_count
FROM users u
INNER JOIN duplicates d ON u.email = d.email
ORDER BY u.email, u.user_id;
```

**이메일 주소가 중복된 모든 레코드 보기**

```
 user_id |         email          | first_name | last_name |         created_at         | duplicate_count 
---------+------------------------+------------+-----------+----------------------------+-----------------
       4 | akua.mansa@example.com | Akua       | Mansa     | 2025-05-21 20:55:53.714432 |               2
       6 | akua.mansa@example.com | Akua       | Mansa     | 2025-05-21 20:55:53.714432 |               2
       1 | john.doe@example.com   | John       | Doe       | 2025-05-21 20:55:53.714432 |               2
       3 | john.doe@example.com   | Johnny     | Doe       | 2025-05-21 20:55:53.714432 |               2
(4 rows)
```

**인덱스 생성 문을 지금 시도하면 실패합니다.**

```
postgres=> CREATE UNIQUE INDEX ASYNC idx_users_email ON users(email);
      job_id      
----------------------------
 ve32upmjz5dgdknpbleeca5tri
(1 row)

postgres=> select * from sys.jobs;
           job_id           |  status   |                       details                       |  job_type   | class_id | object_id |      object_name       |       start_time       |      update_time       
----------------------------+-----------+-----------------------------------------------------+-------------+----------+-----------+------------------------+------------------------+------------------------
 qpn6aqlkijgmzilyidcpwrpova | completed |                                                     | DROP        |     1259 |     26384 |                        | 2025-05-20 00:47:10+00 | 2025-05-20 00:47:32+00
 ve32upmjz5dgdknpbleeca5tri | failed    | Found duplicate key while validating index for UCVs | INDEX_BUILD |     1259 |     26396 | public.idx_users_email | 2025-05-20 00:49:49+00 | 2025-05-20 00:49:56+00
(2 rows)
```

# Aurora DSQL의 시스템 테이블 및 명령
<a name="working-with-systems-tables"></a>

Aurora DSQL에서 지원되는 시스템 테이블 및 카탈로그와 시스템 관련 정보(예: 버전)를 가져오는 데 유용한 쿼리를 알아보려면 다음 섹션을 참조하세요.

## 시스템 테이블
<a name="working-with-system-tables-queries"></a>

Aurora DSQL은 PostgreSQL과 호환되므로 PostgreSQL의 많은 [시스템 카탈로그 테이블](https://www.PostgreSQL.org/docs/current/catalogs-overview.html)과 [뷰](https://www.PostgreSQL.org/docs/current/views.html)가 Aurora DSQL에도 있습니다.

### 중요한 PostgreSQL 카탈로그 테이블 및 뷰
<a name="dsql-catalog-tables"></a>

다음 표에서는 Aurora DSQL에서 사용할 수 있는 가장 일반적인 테이블과 뷰를 설명합니다.


| 이름 | 설명 | 
| --- | --- | 
|  `pg_namespace`  |  모든 스키마에 대한 정보  | 
|  `pg_tables`  |  모든 테이블에 대한 정보  | 
|  `pg_attribute`  |  모든 속성에 대한 정보  | 
|  `pg_views`  |  (미리) 정의된 뷰에 대한 정보  | 
|  `pg_class`  |  모든 테이블, 열, 인덱스 및 유사한 객체 설명  | 
|  `pg_stats`  |  플래너 통계에 대한 뷰  | 
|  `pg_user`  |  사용자에 대한 정보  | 
|  `pg_roles`  |  사용자 및 그룹에 대한 정보  | 
|  `pg_indexes`  |  모든 인덱스 나열  | 
|  `pg_constraint`  |  테이블에 대한 제약 조건 나열  | 

### 지원되는 카탈로그 테이블과 지원되지 않는 카탈로그 테이블
<a name="dsql-catalog-tables-supported"></a>

다음 표에는 Aurora DSQL에서 지원되는 테이블과 지원되지 않는 테이블이 나와 있습니다.


| 이름 | Aurora DSQL에 적용 가능 | 
| --- | --- | 
|  `pg_aggregate`  |  아니요  | 
|  `pg_am`  |  예  | 
|  `pg_amop`  |  아니요  | 
|  `pg_amproc`  |  아니요  | 
|  `pg_attrdef`  |  예  | 
|  `pg_attribute`  |  예  | 
|  `pg_authid`  |  아니요(`pg_roles` 사용)  | 
|  `pg_auth_members`  |  예  | 
|  `pg_cast`  |  예  | 
|  `pg_class`  |  예  | 
|  `pg_collation`  |  예  | 
|  `pg_constraint`  |  예  | 
|  `pg_conversion`  |  아니요  | 
|  `pg_database`  |  아니요  | 
|  `pg_db_role_setting`  |  예  | 
|  `pg_default_acl`  |  예  | 
|  `pg_depend`  |  예  | 
|  `pg_description`  |  예  | 
|  `pg_enum`  |  아니요  | 
|  `pg_event_trigger`  |  아니요  | 
|  `pg_extension`  |  아니요  | 
|  `pg_foreign_data_wrapper`  |  아니요  | 
|  `pg_foreign_server`  |  아니요  | 
|  `pg_foreign_table`  |  아니요  | 
|  `pg_index`  |  예  | 
|  `pg_inherits`  |  예  | 
|  `pg_init_privs`  |  아니요  | 
|  `pg_language`  |  아니요  | 
|  `pg_largeobject`  |  아니요  | 
|  `pg_largeobject_metadata`  |  예  | 
|  `pg_namespace`  |  예  | 
|  `pg_opclass`  |  아니요  | 
|  `pg_operator`  |  예  | 
|  `pg_opfamily`  |  아니요  | 
|  `pg_parameter_acl`  |  예  | 
|  `pg_partitioned_table`  |  아니요  | 
|  `pg_policy`  |  아니요  | 
|  `pg_proc`  |  아니요  | 
|  `pg_publication`  |  아니요  | 
|  `pg_publication_namespace`  |  아니요  | 
|  `pg_publication_rel`  |  아니요  | 
|  `pg_range`  |  예  | 
|  `pg_replication_origin`  |  아니요  | 
|  `pg_rewrite`  |  아니요  | 
|  `pg_seclabel`  |  아니요  | 
|  `pg_sequence`  |  아니요  | 
|  `pg_shdepend`  |  예  | 
|  `pg_shdescription`  |  예  | 
|  `pg_shseclabel`  |  아니요  | 
|  `pg_statistic`  |  예  | 
|  `pg_statistic_ext`  |  아니요  | 
|  `pg_statistic_ext_data`  |  아니요  | 
|  `pg_subscription`  |  아니요  | 
|  `pg_subscription_rel`  |  아니요  | 
|  `pg_tablespace`  |  아니요  | 
|  `pg_transform`  |  아니요  | 
|  `pg_trigger`  |  아니요  | 
|  `pg_ts_config`  |  예  | 
|  `pg_ts_config_map`  |  예  | 
|  `pg_ts_dict`  |  예  | 
|  `pg_ts_parser`  |  예  | 
|  `pg_ts_template`  |  예  | 
|  `pg_type`  |  예  | 
|  `pg_user_mapping`  |  아니요  | 

### 지원되는 시스템 뷰와 지원되지 않는 시스템 뷰
<a name="dsql-system-tables-supported"></a>

다음 표에는 Aurora DSQL에서 지원되는 뷰와 지원되지 않는 뷰가 나와 있습니다.


| 이름 | Aurora DSQL에 적용 가능 | 
| --- | --- | 
|  `pg_available_extensions`  |  아니요  | 
|  `pg_available_extension_versions`  |  아니요  | 
|  `pg_backend_memory_contexts`  |  예  | 
|  `pg_config`  |  아니요  | 
|  `pg_cursors`  |  아니요  | 
|  `pg_file_settings`  |  아니요  | 
|  `pg_group`  |  예  | 
|  `pg_hba_file_rules`  |  아니요  | 
|  `pg_ident_file_mappings`  |  아니요  | 
|  `pg_indexes`  |  예  | 
|  `pg_locks`  |  아니요  | 
|  `pg_matviews`  |  아니요  | 
|  `pg_policies`  |  아니요  | 
|  `pg_prepared_statements`  |  아니요  | 
|  `pg_prepared_xacts`  |  아니요  | 
|  `pg_publication_tables`  |  아니요  | 
|  `pg_replication_origin_status`  |  아니요  | 
|  `pg_replication_slots`  |  아니요  | 
|  `pg_roles`  |  예  | 
|  `pg_rules`  |  아니요  | 
|  `pg_seclabels`  |  아니요  | 
|  `pg_sequences`  |  아니요  | 
|  `pg_settings`  |  예  | 
|  `pg_shadow`  |  예  | 
|  `pg_shmem_allocations`  |  예  | 
|  `pg_stats`  |  예  | 
|  `pg_stats_ext`  |  아니요  | 
|  `pg_stats_ext_exprs`  |  아니요  | 
|  `pg_tables`  |  예  | 
|  `pg_timezone_abbrevs`  |  예  | 
|  `pg_timezone_names`  |  예  | 
|  `pg_user`  |  예  | 
|  `pg_user_mappings`  |  아니요  | 
|  `pg_views`  |  예  | 
|  `pg_stat_activity`  |  아니요  | 
|  `pg_stat_replication`  |  아니요  | 
|  `pg_stat_replication_slots`  |  아니요  | 
|  `pg_stat_wal_receiver`  |  아니요  | 
|  `pg_stat_recovery_prefetch`  |  아니요  | 
|  `pg_stat_subscription`  |  아니요  | 
|  `pg_stat_subscription_stats`  |  아니요  | 
|  `pg_stat_ssl`  |  예  | 
|  `pg_stat_gssapi`  |  아니요  | 
|  `pg_stat_archiver`  |  아니요  | 
|  `pg_stat_io`  |  아니요  | 
|  `pg_stat_bgwriter`  |  아니요  | 
|  `pg_stat_wal`  |  아니요  | 
|  `pg_stat_database`  |  아니요  | 
|  `pg_stat_database_conflicts`  |  아니요  | 
|  `pg_stat_all_tables`  |  아니요  | 
|  `pg_stat_all_indexes`  |  아니요  | 
|  `pg_statio_all_tables`  |  아니요  | 
|  `pg_statio_all_indexes`  |  아니요  | 
|  `pg_statio_all_sequences`  |  아니요  | 
|  `pg_stat_slru`  |  아니요  | 
|  `pg_statio_user_tables`  |  아니요  | 
|  `pg_statio_user_sequences`  |  아니요  | 
|  `pg_stat_user_functions`  |  아니요  | 
|  `pg_stat_user_indexes`  |  아니요  | 
|  `pg_stat_progress_analyze`  |  아니요  | 
|  `pg_stat_progress_basebackup`  |  아니요  | 
|  `pg_stat_progress_cluster`  |  아니요  | 
|  `pg_stat_progress_create_index`  |  아니요  | 
|  `pg_stat_progress_vacuum`  |  아니요  | 
|  `pg_stat_sys_indexes`  |  아니요  | 
|  `pg_stat_sys_tables`  |  아니요  | 
|  `pg_stat_xact_all_tables`  |  아니요  | 
|  `pg_stat_xact_sys_tables`  |  아니요  | 
|  `pg_stat_xact_user_functions`  |  아니요  | 
|  `pg_stat_xact_user_tables`  |  아니요  | 
|  `pg_statio_sys_indexes`  |  아니요  | 
|  `pg_statio_sys_sequences`  |  아니요  | 
|  `pg_statio_sys_tables`  |  아니요  | 
|  `pg_statio_user_indexes`  |  아니요  | 

### sys.jobs 보기
<a name="dsql-sys-jobs"></a>

`sys.jobs`은 비동기 작업에 대한 상태 정보를 제공합니다. 예를 들어 사용자가 [비동기 인덱스를 생성](working-with-create-index-async.md)한 후 Aurora DSQL은 `job_uuid`를 반환합니다. 이 `job_uuid`와 `sys.jobs`을 함께 사용하여 작업 상태를 조회할 수 있습니다.

```
SELECT * FROM sys.jobs;
```

Aurora DSQL은 다음과 유사한 응답을 반환합니다.

```
           job_id           |  status   | details |  job_type   | class_id | object_id |    object_name    |       start_time       |      update_time
----------------------------+-----------+---------+-------------+----------+-----------+-------------------+------------------------+------------------------
 wqhu6ewifze5xitg3umt24h5ua | completed |         | INDEX_BUILD |     1259 |     26433 | public.nt2_c1_idx | 2025-09-25 22:07:31+00 | 2025-09-25 22:07:46+00
 kkngzf33dndl3daacxehpx5eba | completed |         | ANALYZE     |     1259 |     26419 | public.nt         | 2025-09-25 21:57:05+00 | 2025-09-25 21:57:27+00
 fyopxjb6ovdn7po6lrkj63cyea | completed |         | DROP        |     1259 |     26422 |                   | 2025-09-25 22:05:57+00 | 2025-09-25 22:06:03+00
```

다음 표는 `sys.jobs` 보기의 열을 설명합니다.


**sys.jobs 보기 열**  

| 열 | Type | 설명 | 
| --- | --- | --- | 
| job\$1id | text | 작업을 나타내는 base-32 UUID입니다. | 
| status | text | 작업의 현재 상태입니다. 가능한 값은 submitted, processing, completed 및 failed입니다. 자세한 내용은 [sys.jobs 상태 값](#dsql-sys-jobs-status-values) 섹션을 참조하세요. | 
| details | text | 작업에 대한 모든 관련 세부 정보입니다. 작업이 실패하면 자세한 이유가 제공됩니다. | 
| job\$1type | text | 비동기 작업의 유형입니다. 가능한 값은 다음과 같습니다. INDEX\$1BUILD - 비동기식 인덱스 구축. ANALYZE - 시스템에서 제출하는 자동 분석 작업. DROP - DROP TABLE 또는 DROP INDEX 작업 후 물리적 데이터 제거. | 
| class\$1id | oid | 객체가 포함된 카탈로그 테이블의 OID입니다. | 
| object\$1id | oid | 객체의 OID입니다. | 
| object\$1name | text | 객체의 정규화된 이름입니다. DROP 작업은 이미 삭제된 객체를 참조할 수 없습니다. 참조된 객체가 이미 삭제된 경우는 object\$1name은 NULL일 수 있습니다. | 
| start\$1time | timestamp with time zone | 작업이 제출된 타임스탬프입니다. | 
| update\$1time | timestamp with time zone | 작업 행이 마지막으로 업데이트된 타임스탬프입니다. | 


**sys.jobs 상태 값**  

| Status | 설명 | 
| --- | --- | 
| submitted | 작업이 제출되었지만 Aurora DSQL에서 아직 처리를 시작하지 않았습니다. | 
| processing | Aurora DSQL이 작업을 처리하고 있습니다. | 
| failed | 작업이 실패했습니다. 자세한 내용은 details 열을 참조하세요. | 
| completed | Aurora DSQL이 작업을 성공적으로 완료했습니다. | 

### sys.iam\$1pg\$1role\$1mappings 보기
<a name="dsql-sys-iam-pg-role-mappings"></a>

`sys.iam_pg_role_mappings` 뷰는 IAM 사용자에게 부여된 권한에 대한 정보를 제공합니다. 예를 들어 `DQSLDBConnect`가 관리자가 아닌 사용자에게 Aurora DSQL 액세스 권한을 부여하는 IAM 역할이고 `testuser`라는 사용자에게 `DQSLDBConnect` 역할 및 해당 권한이 부여된 경우 `sys.iam_pg_role_mappings` 뷰를 쿼리하여 어떤 사용자에게 어떤 권한이 부여되는지 확인할 수 있습니다.

```
SELECT * FROM sys.iam_pg_role_mappings;
```

## 유용한 시스템 메타데이터 쿼리
<a name="dsql-useful-system-queries"></a>

이러한 쿼리를 사용하면 전체 테이블 스캔과 같이 비용이 많이 드는 작업을 수행하지 않고도 테이블 통계 및 시스템 메타데이터를 가져올 수 있습니다.

### 테이블의 예상 행 수 가져오기
<a name="dsql-get-row-count"></a>

전체 테이블 스캔을 수행하지 않고 테이블의 대략적인 행 수를 가져오려면 다음 쿼리를 사용합니다.

```
SELECT reltuples FROM pg_class WHERE relname = 'table_name';
```

이 명령은 다음과 비슷한 출력을 반환합니다.

```
  reltuples
--------------
 9.993836e+08
```

이 접근 방식은 Aurora DSQL의 `SELECT COUNT(*)` 대형 테이블보다 더 효율적입니다.

### 현재 Aurora DSQL 메이저 버전 확인
<a name="dsql-get-major-version"></a>

Aurora DSQL 클러스터의 현재 메이저 버전을 확인하려면 다음 쿼리를 사용합니다.

```
SELECT * FROM sys.dsql_major_version();
```

이 명령은 다음과 비슷한 출력을 반환합니다.

```
 dsql_major_version
--------------------
                  1
```

이 반환 값은 Aurora DSQL에서 SQL 연결이 활성화된 메이저 버전입니다.

### 현재 PostgreSQL 버전 확인
<a name="dsql-get-pg-version"></a>

Aurora DSQL 클러스터의 현재 PostgreSQL 버전을 확인하려면 다음 쿼리를 사용합니다.

```
SHOW server_version;
```

이 명령은 다음과 비슷한 출력을 반환합니다.

```
 server_version
----------------
 16.13
```

이 반환 값은 Aurora DSQL에서 SQL 연결이 활성화된 PostgreSQL 버전입니다.

## `ANALYZE` 명령
<a name="working-with-system-tables-analyze"></a>

 `ANALYZE `명령은 데이터베이스의 테이블 내용에 대한 통계를 수집하고 결과를 `pg_stats` 시스템 뷰에 저장합니다. 이후 쿼리 플래너는 이러한 통계를 사용하여 쿼리에 대한 가장 효율적인 실행 계획을 결정하는 데 도움을 줍니다.

 Aurora DSQL에서는 명시적 트랜잭션 내에서 `ANALYZE` 명령을 실행할 수 없습니다. `ANALYZE`에는 데이터베이스 트랜잭션 제한 시간이 적용되지 않습니다.

 수동 개입의 필요성을 줄이고 통계를 지속적으로 최신 상태로 유지하기 위해 Aurora DSQL은 `ANALYZE`를 백그라운드 프로세스로 자동으로 실행합니다. 이 백그라운드 작업은 테이블에서 관찰된 변경 속도에 따라 자동으로 트리거됩니다. 마지막 분석 이후 삽입, 업데이트 또는 삭제된 행(튜플) 수와 연결됩니다.

 `ANALYZE`는 백그라운드에서 비동기적으로 실행되며 다음 쿼리를 사용하여 시스템 뷰 sys.jobs에서 활동을 모니터링할 수 있습니다.

```
SELECT * FROM sys.jobs WHERE job_type = 'ANALYZE';
```

**주요 고려 사항**

**참고**  
 `ANALYZE` 작업은 Aurora DSQL의 다른 비동기 작업과 마찬가지로 청구됩니다. 테이블을 수정하면 자동 백그라운드 통계 수집 작업이 간접적으로 트리거되어 연결된 시스템 수준 활동으로 인해 사용량 측정에 따른 요금이 발생할 수 있습니다.

 자동으로 트리거되는 백그라운드 `ANALYZE` 작업은 수동 `ANALYZE`와 동일한 유형의 통계를 수집하여 기본적으로 사용자 테이블에 적용합니다. 시스템 및 카탈로그 테이블은 이 자동 프로세스에서 제외됩니다.

# Aurora DSQL EXPLAIN 계획 작업
<a name="working-with-explain-plans"></a>

Aurora DSQL은 PostgreSQL과 유사한 EXPLAIN 계획 구조를 사용하지만 분산 아키텍처 및 실행 모델을 반영하는 키가 추가되었습니다.

이 설명서에서는 Aurora DSQL EXPLAIN 계획에 대한 개요를 제공하여 PostgreSQL과 비교한 유사성과 차이점을 강조합니다. Aurora DSQL에서 사용할 수 있는 다양한 유형의 스캔 작업을 다루고 쿼리 실행 비용을 이해하는 데 도움이 됩니다.

## PostgreSQL VS Aurora DSQL EXPLAIN 계획
<a name="postgresql-explain-plans"></a>

 Aurora DSQL은 PostgreSQL 데이터베이스를 기반으로 구축되었으며 대부분의 계획 구조를 PostgreSQL과 공유하지만 쿼리 실행 및 최적화에 영향을 미치는 주요 아키텍처 차이점이 있습니다.


| 기능 | PostgreSQL | Aurora DSQL | 
| --- | --- | --- | 
|  데이터 저장  |  힙 스토리지  |  힙 없음, 모든 행이 고유 식별자로 인덱싱됨  | 
|  기본 키  |  프라이머리 키 인덱스는 테이블 데이터와 별개임  |  프라이머리 키 인덱스는 모든 추가 열을 INCLUDE 열로 포함하는 테이블  | 
|  보조 인덱스  |  표준 보조 인덱스  |  키가 아닌 열을 포함할 수 있는 기능으로 PostgreSQL과 동일하게 작업  | 
|  필터링 기능  |  인덱스 조건, 힙 필터  |  인덱스 조건, 스토리지 필터, 쿼리 프로세서 필터   | 
|  스캔 유형  |  순차 스캔, 인덱스 스캔, 인덱스 전용 스캔  |  전체 스캔, 인덱스 전용 스캔, 인덱스 스캔  | 
|  쿼리 실행  |  데이터베이스에 로컬  |  분산(컴퓨팅 및 스토리지는 별도)  | 

Aurora DSQL은 테이블 데이터를 별도의 힙이 아닌 프라이머리 키 순서로 직접 저장합니다. 각 행은 일반적으로 프라이머리 키인 고유 키로 식별되므로 데이터베이스가 조회를 보다 효율적으로 최적화할 수 있습니다. 아키텍처 차이는 PostgreSQL이 인덱스 전용 스캔을 자주 사용하는 이유를 설명합니다.

또 다른 주요 차이점은 Aurora DSQL이 컴퓨팅을 스토리지와 분리하여 실행 경로의 앞부분에서 필터를 적용하여 데이터 이동을 줄이고 성능을 개선할 수 있다는 것입니다.

PostgreSQL에서 EXPLAIN 계획을 사용하는 방법에 대한 자세한 내용은 [PostgreSQL EXPLAIN 설명서](https://www.postgresql.org/docs/current/using-explain.html)를 참조하세요.

## Aurora DSQL EXPLAIN 계획의 주요 요소
<a name="explain-plan-elements"></a>

Aurora DSQL EXPLAIN 계획은 필터링이 발생하는 위치 및 스토리지에서 검색되는 열을 포함하여 쿼리가 실행되는 방법에 대한 자세한 정보를 제공합니다. 이 출력을 이해하면 쿼리 성능을 최적화하는 데 도움이 됩니다.

인덱스 조건  
인덱스를 탐색하는 데 사용되는 조건입니다. 스캔되는 데이터를 줄이는 가장 효율적인 필터링입니다. Aurora DSQL에서는 실행 계획의 여러 계층에 인덱스 조건을 적용할 수 있습니다.

프로젝션  
스토리지에서 검색된 열입니다. 프로젝션이 적을수록 성능이 향상됩니다.

스토리지 필터  
스토리지 수준에서 적용되는 조건입니다. 쿼리 프로세서 필터보다 더 효율적입니다.

쿼리 프로세서 필터  
쿼리 프로세서 수준에서 적용되는 조건입니다. 필터링하기 전에 모든 데이터를 전송해야 하므로 데이터 이동과 처리 오버헤드가 증가합니다.

## Aurora DSQL의 필터
<a name="filtering-and-projection"></a>

Aurora DSQL은 컴퓨팅을 스토리지와 분리하므로 쿼리 실행 중에 필터가 적용되는 지점이 성능에 상당한 영향을 미칩니다. 대량의 데이터가 전송되기 전에 적용되는 필터는 지연 시간을 줄이고 효율성을 개선합니다. 필터가 적용되기 전에는 처리, 이동 및 스캔해야 하는 데이터가 적을수록 쿼리 속도가 빨라집니다.

Aurora DSQL은 쿼리 경로의 여러 단계에서 필터를 적용할 수 있습니다. 이러한 단계를 이해하는 것은 쿼리 계획을 해석하고 성능을 최적화하는 데 중요합니다.


| 수준 | 필터 유형 | 설명 | 
| --- | --- | --- | 
| 1 | 인덱스 조건 |  인덱스를 스캔하는 동안 적용됩니다. 스토리지에서 읽는 데이터의 양을 제한하고 컴퓨팅 계층으로 전송되는 데이터를 줄입니다.  | 
| 2 | 스토리지 필터 | 스토리지에서 데이터를 읽은 후 컴퓨팅으로 전송하기 전에 적용됩니다. 다음은 인덱스의 포함 열에 대한 필터의 예입니다. 데이터 전송은 줄이지만 읽기 양은 줄이지 않습니다. | 
| 3 | 쿼리 프로세서 필터 | 데이터가 컴퓨팅 계층에 도달한 후 적용됩니다. 모든 데이터를 먼저 전송해야 하므로 지연 시간과 비용이 증가합니다. 현재 Aurora DSQL은 스토리지에서 모든 필터링 및 프로젝션 작업을 수행할 수 없으므로, 일부 쿼리는 이러한 유형의 필터링으로 강제로 폴백될 수 있습니다. | 

# Aurora DSQL EXPLAIN 계획 읽기
<a name="reading-dsql-explain-plans"></a>

EXPLAIN 계획을 읽는 방법을 이해하는 것이 쿼리 성능을 최적화하는 데 중요합니다. 이 섹션에서는 Aurora DSQL 쿼리 계획의 실제 예제를 살펴보고, 다양한 스캔 유형이 작동하는 방식을 보여주고, 필터가 적용되는 위치를 설명하고, 최적화 기회를 강조합니다.

## 이 예제에 사용된 샘플 테이블
<a name="explain-plan-sample-tables"></a>

아래 예제에서는 두 테이블 `transaction` 및 `account`를 참조합니다.

`transaction` 테이블에는 프라이머리 키가 없으므로 쿼리할 때 Aurora DSQL이 전체 테이블 스캔을 수행합니다.

`account` 테이블에는 `customer_id`에 대한 인덱스가 있습니다. 이 인덱스는 `balance` 및 `status`를 열로 포함하고 있어 기본 테이블에서 읽지 않고도 특정 쿼리를 인덱스에서 직접 처리할 수 있습니다. 그러나 이 인덱스에는 `created_at`이 포함되지 않으므로 이 열을 참조하는 쿼리에서 추가 테이블 액세스가 필요합니다.

```
CREATE TABLE transaction (
    account_id uuid,
    transaction_date timestamp,
    description text
);

CREATE TABLE account (
    customer_id uuid,
    balance numeric,
    status varchar,
    created_at timestamp
);

CREATE INDEX ASYNC idx1 ON account (customer_id) INCLUDE (balance, status);
```

## 전체 스캔 예제
<a name="full-scan-example"></a>

Aurora DSQL에는 PostgreSQL과 기능적으로 동일한 순차 스캔과 전체 스캔이 모두 있습니다. 이 두 가지의 유일한 차이점은 전체 스캔이 스토리지에서 추가 필터링을 활용할 수 있다는 것입니다. 따라서 거의 항상 순차 스캔보다 먼저 선택됩니다. 유사성으로 인해 더 흥미로운 전체 스캔의 예만 다룹니다.

전체 스캔은 대부분 프라이머리 키가 없는 테이블에서 사용됩니다. Aurora DSQL 프라이머리 키는 기본적으로 전체 커버링 인덱스이므로 Aurora DSQL은 PostgreSQL이 순차 스캔을 사용하는 많은 상황에서 프라이머리 키에 인덱스 전용 스캔을 사용할 가능성이 높습니다. 대부분의 다른 데이터베이스와 마찬가지로 인덱스가 없는 테이블은 잘못 확장됩니다.

```
EXPLAIN SELECT account_id FROM transaction WHERE transaction_date > '2025-01-01' AND description LIKE '%external%';
```

```
                                                   QUERY PLAN
----------------------------------------------------------------------------------------------------------------
 Full Scan (btree-table) on transaction  (cost=125100.05..177933.38 rows=33333 width=16)
   Filter: (description ~~ '%external%'::text)
   -> Storage Scan on transaction (cost=12510.05..17793.38 rows=66666 width=16)
        Projections: account_id, description
        Filters: (transaction_date > '2025-01-01 00:00:00'::timestamp without time zone)
        -> B-Tree Scan on transaction (cost=12510.05..17793.38 rows=100000 width=30)
```

이 계획은 서로 다른 단계에 적용된 두 개의 필터를 보여줍니다. `transaction_date > '2025-01-01'` 조건은 스토리지 계층에 적용되므로 반환되는 데이터의 양이 줄어듭니다. `description LIKE '%external%'` 조건은 데이터가 전송된 후 쿼리 프로세서에서 나중에 적용되므로 효율성이 떨어집니다. 스토리지 또는 인덱스 계층에 더 선택적인 필터를 푸시하면 일반적으로 성능이 향상됩니다.

## 인덱스 전용 스캔 예제
<a name="index-only-scan-example"></a>

인덱스 전용 스캔은 스토리지 계층으로의 왕복이 가장 적기 때문에 Aurora DSQL에서 가장 최적의 스캔 유형이며 가장 많은 필터링을 수행할 수 있습니다. 하지만 인덱스 전용 스캔이 표시되었다고 해서 최상의 계획이 있다는 의미는 아닙니다. 발생할 수 있는 다양한 수준의 필터링으로 인해 필터링이 발생할 수 있는 다양한 위치에 계속 주의를 기울여야 합니다.

```
EXPLAIN SELECT balance FROM account 
WHERE customer_id = '4b18a761-5870-4d7c-95ce-0a48eca3fceb' 
AND balance > 100 
AND status = 'pending';
```

```
                                  QUERY PLAN
-------------------------------------------------------------------------------
 Index Only Scan using idx1 on account  (cost=725.05..1025.08 rows=8 width=18)
   Index Cond: (customer_id = '4b18a761-5870-4d7c-95ce-0a48eca3fceb'::uuid)
   Filter: (balance > '100'::numeric)
   -> Storage Scan on idx1 (cost=12510.05..17793.38 rows=9 width=16)
        Projections: balance
        Filters: ((status)::text = 'pending'::text)
        -> B-Tree Scan on idx1 (cost=12510.05..17793.38 rows=10 width=30)
            Index Cond: (customer_id = '4b18a761-5870-4d7c-95ce-0a48eca3fceb'::uuid)
```

이 계획에서는 인덱스 조건인 `customer_id = '4b18a761-5870-4d7c-95ce-0a48eca3fceb'`가 인덱스 스캔 중에 먼저 평가되는데, 이는 스토리지에서 읽는 데이터의 양을 제한하기 때문에 가장 효율적인 단계입니다. 스토리지 필터 `status = 'pending'`는 데이터를 읽은 후 컴퓨팅 계층으로 전송하기 전에 적용되므로 전송되는 데이터의 양이 줄어듭니다. 마지막으로 쿼리 프로세서 필터 `balance > 100`은 데이터가 이동된 후 마지막으로 실행되므로 효율성이 가장 낮습니다. 이 중 인덱스 조건은 스캔되는 데이터의 양을 직접 제어하기 때문에 최고의 성능을 제공합니다.

## 인덱스 스캔 예제
<a name="index-scan-example"></a>

인덱스 스캔은 기본 테이블을 직접적으로 호출해야 하는 추가 단계가 있다는 점을 제외하면 인덱스 전용 스캔과 유사합니다. Aurora DSQL은 스토리지 필터를 지정할 수 있으므로 인덱스 직접 호출과 조회 직접 호출 모두에서 지정할 수 있습니다.

이를 명확히 하기 위해 Aurora DSQL은 계획을 두 개의 노드로 제공합니다. 이렇게 하면 스토리지에서 반환되는 행 측면에서 포함 열을 추가하는 것이 얼마나 도움이 되는지 명확하게 확인할 수 있습니다.

```
EXPLAIN SELECT balance FROM account 
WHERE customer_id = '4b18a761-5870-4d7c-95ce-0a48eca3fceb'
AND balance > 100 
AND status = 'pending' 
AND created_at > '2025-01-01';
```

```
                                                QUERY PLAN
----------------------------------------------------------------------------------------------------------
 Index Scan using idx1 on account  (cost=728.18..1132.20 rows=3 width=18)
   Filter: (balance > '100'::numeric)
   Index Cond: (customer_id = '4b18a761-5870-4d7c-95ce-0a48eca3fceb'::uuid)
   -> Storage Scan on idx1 (cost=12510.05..17793.38 rows=8 width=16)
        Projections: balance
        Filters: ((status)::text = 'pending'::text)
        -> B-Tree Scan on account (cost=12510.05..17793.38 rows=10 width=30)
            Index Cond: (customer_id = '4b18a761-5870-4d7c-95ce-0a48eca3fceb'::uuid)
   -> Storage Lookup on account (cost=12510.05..17793.38 rows=4 width=16)
        Filters: (created_at > '2025-01-01 00:00:00'::timestamp without time zone)
        -> B-Tree Lookup on transaction (cost=12510.05..17793.38 rows=8 width=30)
```

 이 계획은 여러 단계에서 필터링이 수행되는 방식을 보여 줍니다.
+  `customer_id `의 인덱스 조건은 데이터를 조기에 필터링합니다.
+ `status`의 스토리지 필터는 컴퓨팅으로 전송되기 전에 결과의 범위를 좁힙니다.
+ `balance`의 쿼리 프로세서 필터는 전송 후 나중에 적용됩니다.
+ `created_at`의 조회 필터는 기본 테이블에서 추가 열을 가져올 때 평가됩니다.

자주 사용되는 열을 `INCLUDE` 필드로 추가하면이 조회가 제거되고 성능이 향상될 수 있습니다.

## 모범 사례
<a name="best-practices"></a>
+ **필터를 인덱싱된 열과 정렬**하여 필터링을 이전에 푸시합니다.
+ **INCLUDE 열을 사용**하여 인덱스 전용 스캔을 허용하고 조회를 방지합니다.
+ 성능 문제를 조사할 때 **행 추정치를 검증**합니다. Aurora DSQL은 데이터 변경 속도에 따라 백그라운드에서 `ANALYZE`를 실행하여 통계를 자동으로 관리합니다. 추정치가 부정확해 보이면 `ANALYZE`를 수동으로 실행하여 통계를 즉시 새로 고칠 수 있습니다.
+ 큰 테이블에서 **인덱싱되지 않은 쿼리를 방지**하여 비용이 많이 드는 전체 스캔을 방지합니다.

# EXPLAIN ANALYZE의 DPU 이해
<a name="understanding-dpus-explain-analyze"></a>

Aurora DSQL은 `EXPLAIN ANALYZE VERBOSE` 계획 출력에 **문 수준** 분산 처리 장치(DPU) 정보를 제공하므로 개발 중에 쿼리 비용을 심층적으로 파악할 수 있습니다. 이 섹션에서는 DPU가 무엇이고 `EXPLAIN ANALYZE VERBOSE` 출력에서 해석하는 방법을 설명합니다.

## DPU란?
<a name="what-is-dpu"></a>

분산 처리 장치(DPU)는 Aurora DSQL에서 수행하는 작업의 정규화된 치수입니다. 다음과 같이 구성됩니다.
+ **ComputeDPU** - SQL 쿼리를 실행하는 데 소요된 시간
+ **ReadDPU** - 스토리지에서 데이터를 읽는 데 사용되는 리소스
+ **WriteDPU** - 스토리지에 데이터를 쓰는 데 사용되는 리소스
+ **MultiRegionWriteDPU** - 다중 리전 구성에서 피어링된 클러스터에 쓰기를 복제하는 데 사용되는 리소스입니다.

## EXPLAIN ANALYZE VERBOSE에서 DPU 사용량
<a name="dpu-usage-explain-analyze"></a>

Aurora DSQL은 출력이 끝날 때까지 문 수준 DPU 사용량 추정치를 `EXPLAIN ANALYZE VERBOSE`를 포함하도록 확장됩니다. 이를 통해 쿼리 비용을 즉시 파악할 수 있으므로 워크로드 비용 동인을 식별하고 쿼리 성능을 조정하며 리소스 사용량을 더 잘 예측할 수 있습니다.

다음 예제에서는 EXPLAIN ANALYZE VERBOSE 출력에 포함된 문 수준 DPU 추정치를 해석하는 방법을 보여줍니다.

### 예제 1: SELECT 쿼리
<a name="select-query-example"></a>

```
EXPLAIN ANALYZE VERBOSE SELECT * FROM test_table;
```

```
QUERY PLAN
----------------------------------------------------
Index Only Scan using test_table_pkey on public.test_table  (cost=125100.05..171100.05 rows=1000000 width=36) (actual time=2.973..4.482 rows=120 loops=1)
  Output: id, context
  -> Storage Scan on test_table_pkey (cost=125100.05..171100.05 rows=1000000 width=36) (actual rows=120 loops=1)
      Projections: id, context
      -> B-Tree Scan on test_table_pkey (cost=125100.05..171100.05 rows=1000000 width=36) (actual rows=120 loops=1)
Query Identifier: qymgw1m77maoe
Planning Time: 11.415 ms
Execution Time: 4.528 ms
Statement DPU Estimate:
  Compute: 0.01607 DPU
  Read: 0.04312 DPU
  Write: 0.00000 DPU
  Total: 0.05919 DPU
```

이 예제에서 SELECT 문은 인덱스 전용 스캔을 수행하므로 대부분의 비용은 스토리지에서 검색된 데이터와 결과를 처리하고 반환하는 데 사용되는 컴퓨팅 리소스를 반영하는 컴퓨팅 DPU(0.01607)를 나타내는 읽기 DPU(0.04312)에서 발생합니다. 쿼리는 데이터를 수정하지 않으므로 쓰기 DPU가 없습니다. 총 DPU(0.05919)는 컴퓨팅 \$1 읽기 \$1 쓰기의 합계입니다.

### 예제 2: 쿼리 삽입
<a name="insert-query-example"></a>

```
EXPLAIN ANALYZE VERBOSE INSERT INTO test_table VALUES (1, 'name1'), (2, 'name2'), (3, 'name3');
```

```
QUERY PLAN
----------------------------------------------------
Insert on public.test_table  (cost=0.00..0.04 rows=0 width=0) (actual time=0.055..0.056 rows=0 loops=1)
  ->  Values Scan on "*VALUES*"  (cost=0.00..0.04 rows=3 width=122) (actual time=0.003..0.008 rows=3 loops=1)
        Output: "*VALUES*".column1, "*VALUES*".column2
Query Identifier: jtkjkexhjotbo
Planning Time: 0.068 ms
Execution Time: 0.543 ms
Statement DPU Estimate:
  Compute: 0.01550 DPU
  Read: 0.00307 DPU (Transaction minimum: 0.00375)
  Write: 0.01875 DPU (Transaction minimum: 0.05000)
  Total: 0.03732 DPU
```

이 문은 주로 쓰기를 수행하므로 대부분의 비용이 쓰기 DPU와 연결됩니다. 컴퓨팅 DPU(0.01550)는 값을 처리하고 삽입하기 위해 수행된 작업을 나타냅니다. 읽기 DPU(0.00307)는 마이너 시스템 읽기(카탈로그 조회 또는 인덱스 검사용)를 반영합니다.

읽기 및 쓰기 DPU 옆에 표시된 트랜잭션 최소값을 확인합니다. 이는 *작업에 읽기 또는 쓰기가 포함된 경우에만* 적용되는 기준 트랜잭션당 비용을 나타냅니다. 모든 트랜잭션에 0.00375 읽기 DPU 또는 0.05 쓰기 DPU 요금이 자동으로 부과된다는 의미는 아닙니다. 대신 이러한 최소값은 비용 집계 중에 트랜잭션 수준에서 적용되며 해당 트랜잭션 내에서 읽기 또는 쓰기가 발생하는 경우에만 적용됩니다. 이러한 범위 차이로 인해 `EXPLAIN ANALYZE VERBOSE`의 문 수준 추정치는 CloudWatch 또는 결제 데이터에 보고된 트랜잭션 수준 지표와 정확히 일치하지 않을 수 있습니다.

## 최적화를 위한 DPU 정보 사용
<a name="using-dpu-information-optimization"></a>

문별 DPU 추정치는 실행 시간 이상으로 쿼리를 최적화할 수 있는 강력한 방법을 제공합니다. 일반적인 사용 사례는 다음과 같습니다.
+ **비용 인식:** 쿼리가 다른 쿼리에 비해 얼마나 많은지 이해합니다.
+ **스키마 최적화:** 인덱스 또는 스키마 변경이 성능 및 리소스 효율성에 미치는 영향을 비교합니다.
+ **예산 계획:** 관찰된 DPU 사용량을 기준으로 워크로드 비용을 추정합니다.
+ **쿼리 비교:** 상대적 DPU 사용량을 기준으로 대체 쿼리 접근 방식을 평가합니다.

## DPU 정보 해석
<a name="interpreting-dpu-information"></a>

`EXPLAIN ANALYZE VERBOSE`에서 DPU 데이터를 사용할 때는 다음 모범 사례를 염두에 두세요.
+ **방향에 따라 사용:** 보고된 DPU를 CloudWatch 지표 또는 결제 데이터와 정확히 일치하지 않고 쿼리의 *상대* 비용을 이해하는 방법으로 취급합니다. `EXPLAIN ANALYZE VERBOSE`는 문 수준 비용을 보고하는 반면 CloudWatch는 트랜잭션 수준 활동을 집계하기 때문에 차이가 예상됩니다. CloudWatch에는 `EXPLAIN ANALYZE VERBOSE`에서 의도적으로 제외되는 백그라운드 작업(예: ANALYZE 또는 압축) 및 트랜잭션 오버헤드(`BEGIN`/`COMMIT`)도 포함됩니다.
+ **실행 간 DPU 변동성**은 분산 시스템에서 정상이며 오류를 나타내지 않습니다. 캐싱, 실행 계획 변경, 동시성 또는 데이터 배포의 전환과 같은 요인으로 인해 동일한 쿼리가 한 실행에서 다음 실행으로 서로 다른 리소스를 소비할 수 있습니다.
+ **소규모 작업 배치:** 워크로드에서 작은 문이 많이 발생하는 경우 대규모 작업(10MB를 초과하지 않음)으로 일괄 처리하는 것이 좋습니다. 이렇게 하면 반올림 오버헤드가 줄어들고 더 의미 있는 비용 추정치가 생성됩니다.
+ **결제가 아닌 튜닝에 사용:** `EXPLAIN ANALYZE VERBOSE`의 DPU 데이터는 비용 인식, 쿼리 튜닝 및 최적화를 위해 설계되었습니다. 결제 등급 지표가 아닙니다. 신뢰할 수 있는 비용 및 사용량 데이터는 항상 CloudWatch 지표 또는 월별 결제 보고서에 의존하세요.