

# 테이블에서 데이터를 읽을 때의 관계형(SQL) 데이터베이스와 DynamoDB 비교
<a name="SQLtoNoSQL.ReadData"></a>

SQL에서는 `SELECT` 문을 사용하여 테이블에서 하나 이상의 항목을 가져올 수 있습니다. `WHERE` 절을 사용하여 반환되는 데이터를 결정합니다.

한편, Amazon DynamoDB를 사용하는 경우 데이터를 읽기 위해 다음과 같은 작업이 수행됩니다.
+ `ExecuteStatement`는 테이블에서 단일 또는 여러 개의 항목을 가져옵니다. `BatchExecuteStatement`는 단일 작업으로 서로 다른 테이블에서 여러 항목을 가져옵니다. 이 두 작업 모두 SQL 호환 쿼리 언어 [PartiQL](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.html)을 사용합니다.
+ `GetItem` - 테이블에서 단일 항목을 가져옵니다. 이는 항목의 물리적 위치에 대한 직접 액세스를 제공하기 때문에 단일 항목을 읽는 가장 효율적인 방법입니다. (DynamoDB도 단일 작업으로 최대 100개의 `GetItem` 호출을 수행할 수 있는 `BatchGetItem` 작업을 제공합니다.)
+ `Query` - 특정 파티션 키가 있는 항목을 모두 가져옵니다. 이러한 항목 안에서 키를 정렬하고 데이터의 하위 집합만 가져오도록 조건을 적용할 수 있습니다. `Query`는 데이터가 저장된 파티션에 대한 빠르고 효율적인 액세스를 제공합니다. (자세한 내용은 [DynamoDB의 파티션 및 데이터 배포](HowItWorks.Partitions.md) 섹션을 참조하세요.)
+ `Scan` - 지정한 테이블의 모든 항목을 가져옵니다. (이 작업은 시스템 리소스를 많이 사용할 수 있으므로 큰 테이블에는 사용해서는 안 됩니다.)

**참고**  
관계형 데이터베이스의 경우, `SELECT` 문을 사용하여 여러 테이블의 데이터를 조인하고 결과를 반환할 수 있습니다. 조인은 관계형 모델의 기초입니다. 조인의 효율적 실행을 위해서는 데이터베이스와 그 애플리케이션의 성능을 지속적으로 튜닝해야 합니다. DynamoDB는 비관계형 NoSQL 데이터베이스로서 테이블 조인을 지원하지 않습니다. 그 대신 애플리케이션은 한 번에 한 테이블의 데이터를 읽습니다.

다음 섹션에서는 다양한 데이터 읽기 사용 사례를 설명하고, 관계형 데이터베이스와 DynamoDB로 이런 작업을 수행하는 방법을 살펴봅니다.

**Topics**
+ [프라이머리 키를 사용하여 항목 읽기 비교](SQLtoNoSQL.ReadData.SingleItem.md)
+ [테이블 쿼리 비교](SQLtoNoSQL.ReadData.Query.md)
+ [테이블 스캔 비교](SQLtoNoSQL.ReadData.Scan.md)

# 프라이머리 키를 사용하여 항목 읽기 비교
<a name="SQLtoNoSQL.ReadData.SingleItem"></a>

데이터베이스에 대한 공통적인 액세스 패턴 중 하나는 한 테이블에서 단일 항목을 읽어오는 것입니다. 원하는 항목의 기본 키를 지정해야 합니다.

**Topics**
+ [SQL에서 항목의 프라이머리 키를 사용하여 항목 읽기](#SQLtoNoSQL.ReadData.SingleItem.SQL)
+ [DynamoDB에서 항목의 프라이머리 키를 사용하여 항목 읽기](#SQLtoNoSQL.ReadData.SingleItem.DynamoDB)

## SQL에서 항목의 프라이머리 키를 사용하여 항목 읽기
<a name="SQLtoNoSQL.ReadData.SingleItem.SQL"></a>

SQL에서는 `SELECT` 문을 사용하여 테이블에서 데이터를 가져옵니다. 결과에 하나 이상의 열(또는 `*` 연산자를 사용하는 경우 모든 열)이 포함되도록 요청할 수 있습니다. `WHERE` 절은 반환할 행을 결정합니다.

다음은 *Music* 테이블에서 단일 행을 가져오는 `SELECT` 문입니다. `WHERE` 절은 기본 키 값을 지정합니다.

```
SELECT *
FROM Music
WHERE Artist='No One You Know' AND SongTitle = 'Call Me Today'
```

이 쿼리를 수정하여 열의 하위 집합만 검색할 수 있습니다.

```
SELECT AlbumTitle, Year, Price
FROM Music
WHERE Artist='No One You Know' AND SongTitle = 'Call Me Today'
```

이 테이블의 프라이머리 키는 *Artist* 및 *SongTitle*로 구성되어 있다는 점에 유의하세요.

## DynamoDB에서 항목의 프라이머리 키를 사용하여 항목 읽기
<a name="SQLtoNoSQL.ReadData.SingleItem.DynamoDB"></a>

Amazon DynamoDB에서는 DynamoDB API나 [PartiQL](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.html)(SQL 호환 쿼리 언어)을 사용하여 테이블에서 항목을 읽을 수 있습니다.

------
#### [ DynamoDB API ]

DynamoDB API에서는 `PutItem` 작업을 사용하여 테이블에 항목을 추가합니다.

DynamoDB는 항목을 해당 프라이머리 키를 기준으로 가져오기 위한 `GetItem` 작업을 제공합니다. `GetItem`은 항목의 물리적 위치에 대한 직접 액세스를 제공하므로 매우 효율적입니다. (자세한 내용은 [DynamoDB의 파티션 및 데이터 배포](HowItWorks.Partitions.md) 섹션을 참조하세요.)

기본적으로 `GetItem`은 모든 속성과 함께 전체 항목을 반환합니다.

```
{
    TableName: "Music",
    Key: {
        "Artist": "No One You Know",
        "SongTitle": "Call Me Today"
    }
}
```

속성의 일부만 반환하는 `ProjectionExpression` 파라미터를 추가할 수 있습니다.

```
{
    TableName: "Music",
    Key: {
        "Artist": "No One You Know",
        "SongTitle": "Call Me Today"
    },
    "ProjectionExpression": "AlbumTitle, Year, Price"
}
```

이 테이블의 프라이머리 키는 *Artist* 및 *SongTitle*로 구성되어 있다는 점에 유의하세요.

DynamoDB `GetItem` 작업은 매우 효율적입니다. 프라이머리 키 값을 사용하여 해당 항목의 정확한 스토리지 위치를 확인하고 그 위치에서 직접 항목을 가져옵니다. SQL `SELECT` 문도 기본 키 값을 기준으로 항목을 가져오는 경우에는 마찬가지로 효율적입니다.

SQL `SELECT` 문은 다양한 쿼리 및 테이블 스캔을 지원합니다. DynamoDB는 [테이블 쿼리 비교](SQLtoNoSQL.ReadData.Query.md) 및 [테이블 스캔 비교](SQLtoNoSQL.ReadData.Scan.md)에 설명된 대로 `Query` 및 `Scan` 작업을 통해 이와 비슷한 기능을 제공합니다.

SQL `SELECT` 문은 테이블 조인을 수행하여 한 번에 여러 테이블에서 데이터를 가져올 수 있습니다. 조인은 데이터베이스 테이블들이 정규화되어 있고 테이블 간 관계가 명확한 경우에 가장 효과적입니다. 그러나 하나의 `SELECT` 문에서 지나치게 많은 테이블을 조인하는 경우, 애플리케이션 성능이 영향을 받을 수 있습니다. 이런 문제는 데이터베이스 복제, 구체화된 보기 또는 쿼리 다시 쓰기를 사용하여 해결할 수 있습니다.

DynamoDB는 비관계형 데이터베이스로, 테이블 조인을 지원하지 않습니다. 기존 애플리케이션을 관계형 데이터베이스에서 DynamoDB로 마이그레이션하는 경우, 조인의 필요성을 제거하기 위해 데이터 모델을 비정규화해야 합니다.

------
#### [ PartiQL for DynamoDB ]

PartiQL에서는 PartiQL `Select` 문을 사용하여 `ExecuteStatement` 작업을 통해 테이블에서 항목을 읽습니다.

```
SELECT AlbumTitle, Year, Price
FROM Music
WHERE Artist='No One You Know' AND SongTitle = 'Call Me Today'
```

이 테이블의 프라이머리 키는 Artist 및 SongTitle로 구성되어 있다는 점에 유의하세요.

**참고**  
 Select PartiQL 문은 DynamoDB 테이블을 쿼리하거나 스캔하는 데에도 사용할 수 있습니다.

`Select` 및 `ExecuteStatement`를 사용하는 코드 예제는 [DynamoDB의 PartiQL select 문](ql-reference.select.md) 섹션을 참조하세요.

------

# 테이블 쿼리 비교
<a name="SQLtoNoSQL.ReadData.Query"></a>

또 다른 공통적인 액세스 패턴은 쿼리 기준에 기반하여 한 테이블에서 복수의 항목을 읽어오는 것입니다.

**Topics**
+ [SQL에서 테이블 쿼리](#SQLtoNoSQL.ReadData.Query.SQL)
+ [DynamoDB에서 테이블 쿼리](#SQLtoNoSQL.ReadData.Query.DynamoDB)

## SQL에서 테이블 쿼리
<a name="SQLtoNoSQL.ReadData.Query.SQL"></a>

SQL `SELECT` 문을 사용하여 키 열, 키 이외 열 또는 임의의 조합에서 쿼리를 수행할 수 있습니다. 다음 예제와 같이 `WHERE` 절은 반환되는 행을 결정합니다.

```
/* Return a single song, by primary key */

SELECT * FROM Music
WHERE Artist='No One You Know' AND SongTitle = 'Call Me Today';
```

```
/* Return all of the songs by an artist */

SELECT * FROM Music
WHERE Artist='No One You Know';
```

```
/* Return all of the songs by an artist, matching first part of title */

SELECT * FROM Music
WHERE Artist='No One You Know' AND SongTitle LIKE 'Call%';
```

```
/* Return all of the songs by an artist, only if the price is less than 1.00 */

SELECT * FROM Music
WHERE Artist='No One You Know'
AND Price < 1.00;
```

이 테이블의 프라이머리 키는 *Artist* 및 *SongTitle*로 구성되어 있다는 점에 유의하세요.

## DynamoDB에서 테이블 쿼리
<a name="SQLtoNoSQL.ReadData.Query.DynamoDB"></a>

Amazon DynamoDB에서는 DynamoDB API나 [PartiQL](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.html)(SQL 호환 쿼리 언어)을 사용하여 테이블에서 항목을 쿼리할 수 있습니다.

------
#### [ DynamoDB API ]

Amazon DynamoDB의 `Query` 작업을 사용해도 비슷한 방법으로 데이터를 가져올 수 있습니다. `Query` 작업은 데이터가 저장된 물리적 위치에 대한 빠르고 효율적인 액세스를 제공합니다. 자세한 내용은 [DynamoDB의 파티션 및 데이터 배포](HowItWorks.Partitions.md) 섹션을 참조하세요.

테이블 또는 보조 인덱스와 함께 `Query`를 사용할 수 있습니다. 파티션 키 값에는 등식 조건을 지정해야 하며 지정된 경우 정렬 키 속성에 대해 다른 조건을 선택적으로 지정할 수 있습니다.

`KeyConditionExpression` 파라미터는 쿼리하려는 키 값을 지정합니다. 선택 사항인 `FilterExpression`을 사용하면 반환 전에 일정 항목을 결과에서 제거할 수 있습니다.

DynamoDB에서는 `ExpressionAttributeValues`를 표현식 파라미터(`KeyConditionExpression`, `FilterExpression` 등)에서 자리 표시자로 사용해야 합니다. 이는 런타임에 실제 값을 `SELECT` 문으로 대체하는 관계형 데이터베이스의 *바인드 변수* 사용과 유사합니다.

이 테이블의 프라이머리 키는 *Artist* 및 *SongTitle*로 구성되어 있다는 점에 유의하세요.

다음은 몇 가지 DynamoDB `Query` 예제입니다.

```
// Return a single song, by primary key

{
    TableName: "Music",
    KeyConditionExpression: "Artist = :a and SongTitle = :t",
    ExpressionAttributeValues: {
        ":a": "No One You Know",
        ":t": "Call Me Today"
    }
}
```

```
// Return all of the songs by an artist

{
    TableName: "Music",
    KeyConditionExpression: "Artist = :a",
    ExpressionAttributeValues: {
        ":a": "No One You Know"
    }
}
```

```
// Return all of the songs by an artist, matching first part of title

{
    TableName: "Music",
    KeyConditionExpression: "Artist = :a and begins_with(SongTitle, :t)",
    ExpressionAttributeValues: {
        ":a": "No One You Know",
        ":t": "Call"
    }
}
```

```
// Return all of the songs by an artist, only if the price is less than 1.00

{
    TableName: "Music",
    KeyConditionExpression: "Artist = :a",
    FilterExpression: "Price < :p",
    ExpressionAttributeValues: {
        ":a": "No One You Know",
        ":p": 1.00
    }
}
```

**참고**  
`FilterExpression`은 `Query`가 일치하는 항목을 읽은 후 적용되므로 소비되는 읽기 용량을 줄이지 않습니다. 가능한 경우 범위 조건이 효율적인 쿼리를 위해 정렬 키에 `KeyConditionExpression`을 사용하도록 데이터를 모델링합니다. 자세한 내용은 [DynamoDB에서 테이블 쿼리](Query.md) 섹션을 참조하세요.

------
#### [ PartiQL for DynamoDB ]

PartiQL에서는 `ExecuteStatement` 작업과 파티션 키에 `Select` 문을 사용하여 쿼리를 수행할 수 있습니다.

```
SELECT AlbumTitle, Year, Price
FROM Music
WHERE Artist='No One You Know'
```

이와 같이 `SELECT` 문을 사용하면 이 특정 `Artist`와 연결된 모든 곡이 반환됩니다.

`Select` 및 `ExecuteStatement`를 사용하는 코드 예제는 [DynamoDB의 PartiQL select 문](ql-reference.select.md) 섹션을 참조하세요.

------

# 테이블 스캔 비교
<a name="SQLtoNoSQL.ReadData.Scan"></a>

SQL에서 `SELECT` 절이 없는 `WHERE` 문은 테이블의 모든 행을 반환합니다. Amazon DynamoDB에서 `Scan` 작업도 동일한 작업을 수행합니다. 두 경우 모두 모든 항목 또는 일부 항목만 검색할 수 있습니다.

SQL 데이터베이스를 사용하건 NoSQL 데이터베이스를 사용하건 스캔은 시스템 리소스를 많이 사용할 수 있으므로 꼭 필요할 때만 사용해야 합니다. 스캔이 적절하거나(작은 테이블을 스캔할 때) 불가피한(데이터를 대량으로 내보낼 때) 경우도 있습니다. 하지만 일반적으로는 스캔 수행을 피할 수 있도록 애플리케이션을 설계해야 합니다. 자세한 내용은 [DynamoDB에서 테이블 쿼리](Query.md) 섹션을 참조하세요.

**참고**  
대량 내보내기를 수행하면 파티션당 하나 이상의 파일이 만들어집니다. 각 파일의 모든 항목은 해당 파티션의 해시된 키스페이스에서 가져온 것입니다.

**Topics**
+ [SQL에서 테이블 스캔](#SQLtoNoSQL.ReadData.Scan.SQL)
+ [DynamoDB에서 테이블 스캔](#SQLtoNoSQL.ReadData.Scan.DynamoDB)

## SQL에서 테이블 스캔
<a name="SQLtoNoSQL.ReadData.Scan.SQL"></a>

SQL에서는 `WHERE` 절을 지정하지 않고 `SELECT` 문을 사용하여 테이블을 스캔하고 모든 데이터를 가져올 수 있습니다. 결과에 하나 이상의 열이 포함되도록 요청할 수 있습니다. 또는 와일드카드 문자(\$1)를 사용하는 경우 모든 열을 요청할 수 있습니다.

다음은 `SELECT` 문 사용의 예입니다.

```
/* Return all of the data in the table */
SELECT * FROM Music;
```

```
/* Return all of the values for Artist and Title */
SELECT Artist, Title FROM Music;
```

## DynamoDB에서 테이블 스캔
<a name="SQLtoNoSQL.ReadData.Scan.DynamoDB"></a>

Amazon DynamoDB에서는 DynamoDB API나 SQL [PartiQL](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.html)(호환 쿼리 언어)을 사용하여 테이블에서 스캔을 수행할 수 있습니다.

------
#### [ DynamoDB API ]

DynamoDB API에서는 `Scan` 작업을 통해 테이블 또는 보조 인덱스의 모든 항목에 액세스하여 하나 이상의 항목 및 항목 속성을 반환합니다.

```
// Return all of the data in the table
{
    TableName:  "Music"
}
```

```
// Return all of the values for Artist and Title
{
    TableName:  "Music",
    ProjectionExpression: "Artist, Title"
}
```

`Scan` 작업도 결과에 표시되기를 원치 않는 항목을 삭제하는 데 사용할 수 있는 `FilterExpression` 파라미터를 제공합니다. `FilterExpression`은 스캔이 수행된 후 결과가 반환되기 전에 적용됩니다. (큰 테이블에는 사용하지 않는 것이 좋습니다. 일치하는 소수의 항목이 반환되더라도 여전히 전체 `Scan`에 대한 요금이 청구됩니다.)

------
#### [ PartiQL for DynamoDB ]

PartiQL에서는 `ExecuteStatement` 작업을 통해 `Select` 문을 사용하여 테이블의 모든 내용을 반환하여 스캔을 수행합니다.

```
SELECT AlbumTitle, Year, Price
FROM Music
```

이 문은 Music 테이블에서 모든 항목을 반환합니다.

`Select` 및 `ExecuteStatement`를 사용하는 코드 예제는 [DynamoDB의 PartiQL select 문](ql-reference.select.md) 섹션을 참조하세요.

------