

# Amazon DynamoDB：工作原理
<a name="HowItWorks"></a>

以下章节概述了 Amazon DynamoDB 服务组件及其交互方式。

**Topics**
+ [适用于 DynamoDB 的备忘单](CheatSheet.md)
+ [Amazon DynamoDB 的核心组件](HowItWorks.CoreComponents.md)
+ [DynamoDB API](HowItWorks.API.md)
+ [Amazon DynamoDB 中支持的数据类型和命名规则](HowItWorks.NamingRulesDataTypes.md)
+ [DynamoDB 表类](HowItWorks.TableClasses.md)
+ [DynamoDB 中的分区和数据分布](HowItWorks.Partitions.md)
+ [了解如何从 SQL 转向 NoSQL](SQLtoNoSQL.md)
+ [Amazon DynamoDB 学习资源和工具](AdditionalResources.md)

# 适用于 DynamoDB 的备忘单
<a name="CheatSheet"></a>

本备忘单提供有关使用 Amazon DynamoDB 及其各种 AWS SDK 的快速参考。

## 初始设置
<a name="CheatSheet.InitialSetup"></a>

1. [注册 AWS](SettingUp.DynamoWebService.html#SettingUp.DynamoWebService.SignUpForAWS)。

1. [获取 AWS 访问密钥](SettingUp.DynamoWebService.html#SettingUp.DynamoWebService.GetCredentials)以编程方式访问 DynamoDB。

1. [配置您的 DynamoDB 凭证](SettingUp.DynamoWebService.html#SettingUp.DynamoWebService.ConfigureCredentials)。

**另请参见：**
+ [设置 DynamoDB（Web 服务）](SettingUp.DynamoWebService.html)
+ [DynamoDB 入门](GettingStartedDynamoDB.html)
+ [核心组件的基本概述](HowItWorks.CoreComponents.html)

 

## SDK 或 CLI
<a name="CheatSheet.Platform"></a>

选择您的首选 [SDK](sdk-general-information-section.html)，或设置 [AWS CLI](/cli/latest/index.html)。

**注意**  
在 Windows 上使用 AWS CLI 时，引号之外的反斜杠 (\$1) 被视为回车。另外，您必须转义其他引号内的任何引号和大括号。有关示例，请参阅下一节中“创建表”中的 **Windows** 选项卡。

**另请参见：**
+ [AWS CLIDynamoDB 中的](Tools.CLI.html) 
+ [DynamoDB 入门 - 第 2 步](getting-started-step-2.html)

## 基本操作
<a name="CheatSheet.BasicActions"></a>

本节提供基本 DynamoDB 任务的代码。有关这些任务的更多信息，请参阅 [DynamoDB 入门和 AWS SDK](GettingStarted.html)。

### 创建表
<a name="CheatSheet.BasicActions.CreateTable"></a>

------
#### [ Default ]

```
aws dynamodb create-table \
    --table-name Music \
    --attribute-definitions \
        AttributeName=Artist,AttributeType=S \
        AttributeName=SongTitle,AttributeType=S \
    --key-schema AttributeName=Artist,KeyType=HASH AttributeName=SongTitle,KeyType=RANGE \
    --billing-mode PAY_PER_REQUEST \
    --table-class STANDARD
```

------
#### [ Windows ]

```
aws dynamodb create-table ^
    --table-name Music ^
    --attribute-definitions ^
        AttributeName=Artist,AttributeType=S ^
        AttributeName=SongTitle,AttributeType=S ^
    --key-schema AttributeName=Artist,KeyType=HASH AttributeName=SongTitle,KeyType=RANGE ^
    --billing-mode PAY_PER_REQUEST ^
    --table-class STANDARD
```

------

### 在表中写入项目
<a name="CheatSheet.BasicActions.WriteItem"></a>

```
aws dynamodb put-item \ --table-name Music \ --item file://item.json
```

### 从表中读取项目
<a name="CheatSheet.BasicActions.ReadItem"></a>

```
aws dynamodb get-item \ --table-name Music \ --item file://item.json
```

### 从表中删除项目
<a name="CheatSheet.BasicActions.DeleteItem"></a>

```
aws dynamodb delete-item --table-name Music --key file://key.json
```

### 查询表
<a name="CheatSheet.BasicActions.QueryTable"></a>

```
aws dynamodb query --table-name Music 
--key-condition-expression "ArtistName=:Artist and SongName=:Songtitle"
```

### 删除表
<a name="CheatSheet.BasicActions.DeleteTable"></a>

```
aws dynamodb delete-table --table-name Music
```

### 列出表名
<a name="CheatSheet.BasicActions.ListTableNames"></a>

```
aws dynamodb list-tables
```

## 命名规则
<a name="CheatSheet.NamingRules"></a>
+ 所有名称都必须使用 UTF-8 进行编码，并且区分大小写。
+ 表名称和索引名称的长度必须介于 3 到 255 个字符之间，而且只能包含以下字符：
  + `a-z`
  + `A-Z`
  + `0-9`
  + `_`（下划线）
  + `-`（连字符）
  + `.`（圆点）
+ 属性名称的长度必须至少为 1 个字符，但大小小于 64KB。

有关更多信息，请参阅[命名规则](HowItWorks.NamingRulesDataTypes.html)。

## 服务配额基础知识
<a name="CheatSheet.ServiceBasics"></a>

**读取和写入单位**
+ **读取容量单位 (RCU)** – 对于 4KB 及以下数据量的项目，每秒一次强一致性读取，或每秒两次最终一致性读取。
+ **写入容量单位 (WCU)** – 对于 1KB 及以下数据量的项目，每秒一次写入。

**表限制**
+ **表限制** – 表的大小实际上没有限制。表的项目数和字节数是无限制的。
+ **表数** – 对于任何 AWS 账户，每个 AWS 区域的初始配额为 2,500 个表。
+ **查询和扫描的页面大小限制** – 每个查询或扫描的每页大小限制为 1MB。如果您在一个表上的查询参数或扫描操作产生的数据超过 1MB，DynamoDB 将返回初始匹配项。它还返回一个 `LastEvaluatedKey` 属性，可用于阅读下一页的新请求中。

**索引**
+ **本地二级索引 (LSI)** - 您最多可以定义五个本地二级索引。当索引必须与基表存在强一致性时，LSI 相当有用。
+ **全局二级索引 (GSI)** – 每个表默认具有 20 个全局二级索引配额。
+ **每个表的投影二级索引属性** – 您最多可将总共 100 个属性投影到一个表的所有本地和全局二级索引，此限制只适用于用户指定的投影属性。

**分区键**
+ 分区键值的最小长度为 1 个字节，最大长度为 2048 个字节。
+ 表和二级索引的不同分区键值的数量没有实际限制。
+ 排序键值的最小长度为 1 个字节。最大长度为 1024 个字节。
+ 一般情况下，每个分区键值的不同排序键值的数量没有实际限制。具有二级索引的表则例外。

有关二级索引、分区键设计和排序键设计的更多信息，请参阅[最佳实践](best-practices.html)。

**常用数据类型的限制**
+ **字符串** – 字符串的长度受到项目大小最多为 400KB 的约束。字符串是使用 UTF-8 二进制编码的 Unicode。
+ **数值** – 数值可具有最多 38 位精度，并且可以是正数、负数或零。
+ **二进制** – 二进制的长度受到项目大小最多为 400KB 的约束。使用二进制属性的应用程序必须先用 Base64 格式对数据进行编码，然后才能将数据发送至 DynamoDB。

有关受支持的数据类型的完整列表，请参阅[数据类型](HowItWorks.NamingRulesDataTypes.html#HowItWorks.DataTypes)。有关更多信息，请参阅[服务配额](ServiceQuotas.html#limits-items)。

### 项目、属性和表达式参数
<a name="CheatSheet.ServiceBasics.Misc"></a>

DynamoDB 中的项目大小最多为 400KB，包括属性名称二进制长度加上属性值二进制长度，二者均为 UTF-8 长度。属性名称也包含在此大小限制之内。

列表、映射或集中值的数量没有限制，只要包含值的项目大小不超过 400KB 的限制即可。

关于表达式参数，任何表达式字符串的最大长度为 4KB。

有关项目大小、属性和表达式参数的更多信息，请参阅[服务配额](ServiceQuotas.html#limits-items)。

## 更多信息
<a name="CheatSheet.FurtherInfo"></a>
+ [安全性](security.html)。
+ [监控和日志记录](monitoring.html)
+ [处理流](streamsmain.html)
+ [备份](Backup-and-Restore.html)和[时间点故障恢复](Point-in-time-recovery.html)
+ [与其他 AWS 服务集成](OtherServices.html) 
+ [API 参考](/amazondynamodb/latest/APIReference/Welcome.html)
+ [架构中心：数据库最佳实践](https://aws.amazon.com/architecture/databases/)
+ [教程视频](https://youtu.be/Mw8wCj0gkRc)
+ [DynamoDB 论坛](https://repost.aws/search/questions?globalSearch=dynamodb)

# Amazon DynamoDB 的核心组件
<a name="HowItWorks.CoreComponents"></a>

在 DynamoDB 中，表、项目和属性是您使用的核心组件。*表*是*项目*的集合，而每个项目是*属性*的集合。DynamoDB 使用主键来唯一标识表中的各个项目。您可以使用 DynamoDB Streams 捕获 DynamoDB 表中的数据修改事件。

 DynamoDB 中存在限制。有关更多信息，请参阅 [Amazon DynamoDB 中的配额](ServiceQuotas.md)。

以下视频将向您介绍表、项目和属性。

[表、项目和属性](https://www.youtube.com/embed/Mw8wCj0gkRc)

## 表、项目和属性
<a name="HowItWorks.CoreComponents.TablesItemsAttributes"></a>

![\[每个 DynamoDB 表都包含零个或多个由一个或多个属性组成的项目。\]](http://docs.aws.amazon.com/zh_cn/amazondynamodb/latest/developerguide/images/HowItWorksTables-2024.png)


以下是基本的 DynamoDB 组件：
+ **表** – 类似于其他数据库系统，DynamoDB 将数据存储在表中。*表* 是数据的集合。例如，请参阅名为 *People* 的示例表，该表可用于存储有关好友、家人或关注的任何其他人的个人联系信息。您也可以建立一个 *Cars* 表，存储有关人们所驾驶的车辆的信息。
+ **项目** – 每个表包含零个或更多个项目。*项目* 是一组属性，具有不同于所有其他项目的唯一标识。在 *People* 表中，每个项目表示一位人员。在 *Cars* 表中，每个项目代表一种车。DynamoDB 中的项目在很多方面都类似于其他数据库系统中的行、记录或元组。在 DynamoDB 中，对表中可存储的项目数没有限制。
+ **属性** – 每个项目包含一个或多个属性。*属性* 是基础的数据元素，无需进一步分解。例如，*People* 表中的一个项目包含名为 *PersonID*、*LastName*、*FirstName* 等的属性。对于 *Department* 表，项目可能包含 *DepartmentID*、*Name*、*Manager* 等属性。DynamoDB 中的属性在很多方面都类似于其他数据库系统中的字段或列。

下图是一个名为 *People* 的表，其中显示了一些示例项目和属性。

```
People

{
    "PersonID": 101,
    "LastName": "Smith",
    "FirstName": "Fred",
    "Phone": "555-4321"
}

{
    "PersonID": 102,
    "LastName": "Jones",
    "FirstName": "Mary",
    "Address": {
                "Street": "123 Main",
                "City": "Anytown",
                "State": "OH",
                "ZIPCode": 12345
    }
}

{
    "PersonID": 103,
    "LastName": "Stephens",
    "FirstName": "Howard",
    "Address": {
                "Street": "123 Main",
                "City": "London",                                    
                "PostalCode": "ER3 5K8"
    },
    "FavoriteColor": "Blue"
}
```

请注意有关 *People* 表的以下事项：
+ 表中的每个项目都有一个唯一的标识符或主键，用于将项目与表中的所有其他内容区分开来。在 *People* 表中，主键包含一个属性 (*PersonID*)。
+ 与主键不同，*People* 表是无架构的，这表示属性及其数据类型都不需要预先定义。每个项目都能拥有其自己的独特属性。
+ 大多数属性是*标量* 类型的，这表示它们只能具有一个值。字符串和数字是标量的常见示例。
+ 某些项目具有嵌套属性 (*Address*)。DynamoDB 支持高达 32 级深度的嵌套属性。

下面是名为 *Music* 的另一个示例表，该表可用于跟踪音乐精选。

```
Music

{
    "Artist": "No One You Know",
    "SongTitle": "My Dog Spot",
    "AlbumTitle": "Hey Now",
    "Price": 1.98,
    "Genre": "Country",
    "CriticRating": 8.4
}

{
    "Artist": "No One You Know",
    "SongTitle": "Somewhere Down The Road",
    "AlbumTitle": "Somewhat Famous",
    "Genre": "Country",
    "CriticRating": 8.4,
    "Year": 1984
}

{
    "Artist": "The Acme Band",
    "SongTitle": "Still in Love",
    "AlbumTitle": "The Buck Starts Here",
    "Price": 2.47,
    "Genre": "Rock",
    "PromotionInfo": {
        "RadioStationsPlaying": [
            "KHCR",
            "KQBX",
            "WTNR",
            "WJJH"
        ],
        "TourDates": {
            "Seattle": "20150622",
            "Cleveland": "20150630"
        },
        "Rotation": "Heavy"
    }
}

{
    "Artist": "The Acme Band",
    "SongTitle": "Look Out, World",
    "AlbumTitle": "The Buck Starts Here",
    "Price": 0.99,
    "Genre": "Rock"
}
```

请注意有关 *Music* 表的以下事项：
+ *Music* 的主键包含两个属性（*Artist* 和 *SongTitle*）。表中的每个项目必须具有这两个属性。*Artist* 和 *SongTitle* 的属性组合用于将表中的每个项目与所有其他内容区分开来。
+ 与主键不同，*Music* 表是无架构的，这表示属性及其数据类型都不需要预先定义。每个项目都能拥有其自己的独特属性。
+ 其中一个项目具有嵌套属性 (*PromotionInfo*)，该属性包含其他嵌套属性。DynamoDB 支持高达 32 级深度的嵌套属性。

 有关更多信息，请参阅 [使用 DynamoDB 中的表和数据](WorkingWithTables.md)。

## 主键
<a name="HowItWorks.CoreComponents.PrimaryKey"></a>

创建表时，除表名称外，您还必须指定表的主键。主键唯一标识表中的每个项目，因此，任意两个项目的主键都不相同。

DynamoDB 支持两种不同类型的主键：
+ **分区键** – 由一个称为*分区键*的属性构成的简单主键。

  DynamoDB 使用分区键的值作为内部散列函数的输入。来自散列函数的输出决定了项目将存储到的分区（DynamoDB 内部的物理存储）。

   在只有分区键的表中，任何两个项目都不能有相同的分区键值。

  [表、项目和属性](#HowItWorks.CoreComponents.TablesItemsAttributes) 的 *People* 表具有简单主键 (*PersonID*)。您可以直接访问 *People* 表中的任何项目，方法是提供该项目的 *PersonId* 值。
+ **分区键和排序键** – 称为*复合主键*，此类型的键由两个属性组成。第一个属性是*分区键*，第二个属性是*排序键*。

  DynamoDB 使用分区键值作为对内部哈希函数的输入。来自散列函数的输出决定了项目将存储到的分区（DynamoDB 内部的物理存储）。具有相同分区键值的所有项目按排序键值的排序顺序存储在一起。

  在具有分区键和排序键的表中，多个项目可能具有相同的分区键值。但是，这些项目必须具有不同的排序键值。

  [表、项目和属性](#HowItWorks.CoreComponents.TablesItemsAttributes) 的 *Music* 表是具有复合主键（*Artist* 和 *SongTitle*）的表示例。您可以直接访问 *Music* 表中的任何项目，方法是提供该项目的 *Artist* 和 *SongTitle* 值。

  在查询数据时，复合主键可让您获得额外的灵活性。例如，如果您仅提供了 *Artist* 的值，则 DynamoDB 将检索该艺术家的所有歌曲。要仅检索特定艺术家的一部分歌曲，您可以提供一个 *Artist* 值和一系列 *SongTitle* 值。

**注意**  
项目的分区键也称为其*哈希属性*。*哈希属性*一词源自 DynamoDB 中使用的内部哈希函数，以基于数据项目的分区键值实现跨多个分区的数据项目平均分布。  
项目的排序键也称为其*范围属性*。*范围属性*一词源自 DynamoDB 存储项目的方式，它按照排序键值有序地将具有相同分区键的项目存储在互相紧邻的物理位置。

每个主键属性必须为标量 (表示它只能具有一个值)。主键属性唯一允许的数据类型是字符串、数字和二进制。对于其他非键属性没有任何此类限制。

## 二级索引
<a name="HowItWorks.CoreComponents.SecondaryIndexes"></a>

您可以在一个表上创建一个或多个二级索引。利用*二级索引*，除了可对主键进行查询外，还可使用替代键查询表中的数据。DynamoDB 不需要使用索引，为应用程序提供数据查询方面的更大的灵活性。在表中创建二级索引后，您可以从索引中读取数据，方法与从表中读取数据大体相同。

DynamoDB 支持两种索引：
+ 全局二级索引 – 分区键和排序键可与基表中的这些键不同的索引。全局二级索引中的主键值无需唯一。
+ 本地二级索引 – 分区键与基表相同但排序键不同的索引。

在 DynamoDB 中，全局二级索引（GSI）是跨整个表的索引，允许您跨所有分区键进行查询。本地二级索引（LSI）的分区键与基表相同，但排序键不同。

DynamoDB 中的每个表具有 20 个全局二级索引（默认配额）和 5 个本地二级索引的配额。

在前面显示的示例 *Music* 表中，您可以按 *Artist*（分区键）或按 *Artist* 和 *SongTitle*（分区键和排序键）查询数据项。如果您还想要按 *Genre* 和 *AlbumTitle* 查询数据，该怎么办？ 若要达到此目的，您可在 *Genre* 和 *AlbumTitle* 上创建一个索引，然后通过与查询 *Music* 表相同的方式查询索引。

下图显示了示例 *Music* 表，该表包含一个名为 *GenreAlbumTitle* 的新索引。在索引中，*Genre* 是分区键，*AlbumTitle* 是排序键。


| Music 表 | *GenreAlbumTitle* | 
| --- | --- | 
|  <pre><br />{<br />    "Artist": "No One You Know",<br />    "SongTitle": "My Dog Spot",<br />    "AlbumTitle": "Hey Now",<br />    "Price": 1.98,<br />    "Genre": "Country",<br />    "CriticRating": 8.4<br />}                               <br />                                </pre>  |  <pre><br />{<br />    "Genre": "Country",<br />    "AlbumTitle": "Hey Now",<br />    "Artist": "No One You Know",<br />    "SongTitle": "My Dog Spot"<br />}<br />                                </pre>  | 
|  <pre><br />{<br />    "Artist": "No One You Know",<br />    "SongTitle": "Somewhere Down The Road",<br />    "AlbumTitle": "Somewhat Famous",<br />    "Genre": "Country",<br />    "CriticRating": 8.4,<br />    "Year": 1984<br />}<br />                                </pre>  |  <pre><br />{<br />    "Genre": "Country",<br />    "AlbumTitle": "Somewhat Famous",<br />    "Artist": "No One You Know",<br />    "SongTitle": "Somewhere Down The Road"<br />}<br />                                </pre>  | 
|  <pre><br />{<br />    "Artist": "The Acme Band",<br />    "SongTitle": "Still in Love",<br />    "AlbumTitle": "The Buck Starts Here",<br />    "Price": 2.47,<br />    "Genre": "Rock",<br />    "PromotionInfo": {<br />        "RadioStationsPlaying": {<br />            "KHCR",<br />            "KQBX",<br />            "WTNR",<br />            "WJJH"<br />        },<br />        "TourDates": {<br />            "Seattle": "20150622",<br />            "Cleveland": "20150630"<br />        },<br />        "Rotation": "Heavy"<br />    }<br />}<br />                                </pre>  |  <pre><br />{<br />    "Genre": "Rock",<br />    "AlbumTitle": "The Buck Starts Here",<br />    "Artist": "The Acme Band",<br />    "SongTitle": "Still In Love"<br />}<br />                                </pre>  | 
|  <pre><br />{<br />    "Artist": "The Acme Band",<br />    "SongTitle": "Look Out, World",<br />    "AlbumTitle": "The Buck Starts Here",<br />    "Price": 0.99,<br />    "Genre": "Rock"<br />}<br />                                </pre>  |  <pre><br />{<br />    "Genre": "Rock",<br />    "AlbumTitle": "The Buck Starts Here",<br />    "Artist": "The Acme Band",<br />    "SongTitle": "Look Out, World"<br />}<br />                                </pre>  | 

请注意有关 *GenreAlbumTitle* 索引的以下事项：
+ 每个索引属于一个表（称为索引的*基表*）。在上述示例中，*Music* 是 *GenreAlbumTitle* 索引的基表。
+ DynamoDB 将自动维护索引。当您添加、更新或删除基表中的某个项目时，DynamoDB 会添加、更新或删除属于该表的任何索引中的对应项目。
+ 当您创建索引时，可指定哪些属性将从基表复制或*投影* 到索引。DynamoDB 至少会将键属性从基表投影到索引中。对于 `GenreAlbumTitle` 也是如此，只不过此时只有 `Music` 表中的键属性会投影到索引中。

您可以查询 *GenreAlbumTitle* 索引以查找某个特定流派的所有专辑（例如，所有 *Rock* 专辑）。您还可以查询索引以查找特定流派中具有特定专辑名称的所有专辑（例如，名称以字母 H 开头的所有 *Country* 专辑）。

有关更多信息，请参阅 [在 DynamoDB 中使用二级索引改进数据访问](SecondaryIndexes.md)。

## DynamoDB Streams
<a name="HowItWorks.CoreComponents.Streams"></a>

DynamoDB Streams 是一项可选功能，用于捕获 DynamoDB 表中的数据修改事件。有关这些事件的数据将以事件发生的顺序近乎实时地出现在流中。

每个事件由一条*流记录* 表示。如果您对表启用流，则每当以下事件之一发生时，DynamoDB Streams 都会写入一条流记录：
+ 向表中添加了新项目：流将捕获整个项目的映像，包括其所有属性。
+ 更新了项目：流将捕获项目中已修改的任何属性的“之前”和“之后”映像。
+ 从表中删除了项目：流将在整个项目被删除前捕获其映像。

每条流记录还包含表的名称、事件时间戳和其他元数据。流记录具有 24 个小时的生命周期；在此时间过后，它们将从流中自动删除。

您可以将 DynamoDB Streams 与 AWS Lambda 结合使用以创建*触发器*—在流中有您感兴趣的事件出现时自动执行的代码。例如，假设有一个包含某公司客户信息的 *Customers* 表。假设您希望向每位新客户发送一封“欢迎”电子邮件。您可对该表启用一个流，然后将该流与 Lambda 函数关联。Lambda 函数将在新的流记录出现时执行，但只会处理添加到 *Customers* 表的新项目。对于具有 `EmailAddress` 属性的任何项目，Lambda 函数将调用 Amazon Simple Email Service (Amazon SES) 以向该地址发送电子邮件。

![\[将 DynamoDB Streams 与 Lambda 集成，从而自动向新客户发送欢迎电子邮件。\]](http://docs.aws.amazon.com/zh_cn/amazondynamodb/latest/developerguide/images/HowItWorksStreams.png)


**注意**  
在此示例中，最后一位客户 Craig Roe 将不会收到电子邮件，因为他没有 `EmailAddress`。

除了触发器之外，DynamoDB Streams 还提供了强大的解决方案，例如，AWS 区域内和区域之间的数据复制、DynamoDB 表中的数据具体化视图、使用 Kinesis 具体化视图的数据分析等。

有关更多信息，请参阅 [将更改数据捕获用于 DynamoDB Streams](Streams.md)。

# DynamoDB API
<a name="HowItWorks.API"></a>

要使用 Amazon DynamoDB，您的应用程序必须使用一些简单的 API 操作。下面汇总了这些操作（按类别组织）。

**注意**  
有关 API 操作的完整列表，请参阅 [Amazon Athena API 参考](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/Welcome.html)。

**Topics**
+ [控制面板](#HowItWorks.API.ControlPlane)
+ [数据面板](#HowItWorks.API.DataPlane)
+ [DynamoDB Streams](#HowItWorks.API.Streams)
+ [事务](#HowItWorks.API.Transactions)

## 控制面板
<a name="HowItWorks.API.ControlPlane"></a>

*控制层面*操作可让您可以创建和管理 DynamoDB 表。还可以支持您使用依赖于表的索引、流和其他对象。
+  `CreateTable` – 创建新表。或者，您也可以创建一个或多个二级索引并为表启用 DynamoDB Streams。
+ `DescribeTable`– 返回有关表的信息，例如，表的主键架构、吞吐量设置和索引信息。
+ `ListTables` – 返回列表中您的所有表的名称。
+ `UpdateTable` – 修改表或其索引的设置、创建或删除表上的新索引或修改表的 DynamoDB Streams 设置。
+ `DeleteTable` – 从 DynamoDB 中删除表及其所有依赖对象。

## 数据面板
<a name="HowItWorks.API.DataPlane"></a>

*数据层面* 操作可让您对表中的数据执行创建、读取、更新和删除（也称为 *CRUD*）操作。某些数据层面操作还可从二级索引读取数据。

您可以使用 [PartiQL – 用于 Amazon DynamoDB 的 SQL 兼容语言](ql-reference.md) 来执行这些 CRUD 操作，也可以使用 DynamoDB 的经典 CRUD API，将每个操作分离为不同的 API 调用。

### PartiQL – 一种与 SQL 兼容的查询语言
<a name="HowItWorks.API.DataPlane.partiql"></a>
+ `ExecuteStatement`— 从表中读取多个项目。您还可以写入或更新表的单个项目。当写入或更新单个项目时，您必须指定主键属性。
+ `BatchExecuteStatement`— 写入、更新或读取表中的多个项目。这比 `ExecuteStatement` 更有效，因为您的应用程序只需一个网络往返行程即可写入或读取项目。

### 经典 API
<a name="HowItWorks.API.DataPlane.classic"></a>

#### 创建数据
<a name="HowItWorks.API.DataPlane.Create"></a>
+ `PutItem` - 将单个项目写入表中。您必须指定主键属性，但不必指定其他属性。
+ `BatchWriteItem` – 将最多 25 个项目写入到表。这比多次调用 `PutItem` 更有效，因为您的应用程序只需一个网络往返行程即可写入项目。

#### 读取数据
<a name="HowItWorks.API.DataPlane.Read"></a>
+ `GetItem` - 从表中检索单个项目。您必须为所需的项目指定主键。您可以检索整个项目，也可以仅检索其属性的子集。
+ `BatchGetItem` – 从一个或多个表中检索最多 100 个项目。这比多次调用 `GetItem` 更有效，因为您的应用程序只需一个网络往返行程即可读取项目。
+ `Query` - 检索具有特定分区键的所有项目。您必须指定分区键值。您可以检索整个项目，也可以仅检索其属性的子集。或者，您也可以对排序键值应用条件，以便只检索具有相同分区键的数据子集。您可以对表使用此操作，前提是该表同时具有分区键和排序键。您还可以对索引使用此操作，前提是该索引同时具有分区键和排序键。
+ `Scan` - 检索指定表或索引中的所有项目。您可以检索整个项目，也可以仅检索其属性的子集。或者，您也可以应用筛选条件以仅返回您感兴趣的值并放弃剩余的值。

#### 更新数据
<a name="HowItWorks.API.DataPlane.Update"></a>
+ `UpdateItem` - 修改项目中的一个或多个属性。您必须为要修改的项目指定主键。您可以添加新属性并修改或删除现有属性。您还可以执行有条件更新，以便更新仅在满足用户定义的条件时成功。或者，您也可以实施一个原子计数器，该计数器可在不干预其他写入请求的情况下递增或递减数字属性。

#### 删除数据
<a name="HowItWorks.API.DataPlane.Delete"></a>
+ `DeleteItem` - 从表中删除单个项目。您必须为要删除的项目指定主键。
+ `BatchWriteItem` – 从一个或多个表中删除最多 25 个项目。这比多次调用 `DeleteItem` 更有效，因为您的应用程序只需一个网络往返行程即可删除项目。
**注意**  
您可以使用 `BatchWriteItem` 创建数据和删除数据。

## DynamoDB Streams
<a name="HowItWorks.API.Streams"></a>

*DynamoDB Streams* 操作可让您对表启用或禁用流，并能允许对包含在流中的数据修改记录的访问。
+ `ListStreams` - 返回您的所有流的列表，或仅返回特定表的流。
+ `DescribeStream` - 返回有关流的信息，例如，流的 Amazon 资源名称（ARN）和您的应用程序可开始读取前几条流记录的位置。
+ `GetShardIterator` – 返回一个*分片迭代器*，这是您的应用程序用来从流中检索记录的数据结构。
+ `GetRecords` - 使用给定分片迭代器检索一条或多条流记录。

## 事务
<a name="HowItWorks.API.Transactions"></a>

*事务* 提供原子性、一致性、隔离性和持久性 (ACID)，使您能够更轻松地维护应用程序中的数据正确性。

您可以使用 [PartiQL – 用于 Amazon DynamoDB 的 SQL 兼容语言](ql-reference.md) 来执行事务操作，也可以使用 DynamoDB 的经典 CRUD API，将每个操作分离为不同的 API 调用。

### PartiQL – 一种与 SQL 兼容的查询语言
<a name="HowItWorks.API.Transactions.DataPlane.partiql"></a>
+ `ExecuteTransaction` – 一种批处理操作，用于在表内和跨表对多个项目执行 CRUD 操作，并保证得到全有或全无结果。

### 经典 API
<a name="HowItWorks.API.DataPlane.classic"></a>
+ `TransactWriteItems` – 一种批处理操作，用于在表内和跨表对多个项目执行 `Put`、`Update` 和 `Delete` 操作，并保证得到全有或全无结果。
+ `TransactGetItems` – 一种批处理操作，用于执行 `Get` 操作以从一个或多个表检索多个项目。

# Amazon DynamoDB 中支持的数据类型和命名规则
<a name="HowItWorks.NamingRulesDataTypes"></a>

本部分介绍 Amazon DynamoDB 命名规则和 DynamoDB 支持的各种数据类型。数据类型存在限制。有关更多信息，请参阅 [数据类型](Constraints.md#limits-data-types)。

**Topics**
+ [命名规则](#HowItWorks.NamingRules)
+ [数据类型](#HowItWorks.DataTypes)
+ [数据类型描述符](#HowItWorks.DataTypeDescriptors)

## 命名规则
<a name="HowItWorks.NamingRules"></a>

DynamoDB 中的表、属性和其他对象必须具有名称。名称应该简明扼要，例如，*Products*、*Books* 和 *Authors* 之类的名称是都是不言而喻的。

下面是 DynamoDB 的命名规则：
+ 所有名称都必须使用 UTF-8 进行编码，并且区分大小写。
+ 表名称和索引名称的长度必须介于 3 到 255 个字符之间，而且只能包含以下字符：
  + `a-z`
  + `A-Z `
  + ` 0-9 `
  + `_`（下划线）
  + `-`（短划线）
  + `.`（圆点）
+ 属性名称的长度必须至少为 1 个字符，但大小小于 64KB。最佳实践是使属性名称尽可能短。这有助于减少占用的读取请求单位数量，因为属性名称包含在存储和吞吐量使用量的计量中。

  存在以下例外。这些属性名称的长度不得超过 255 个字符：
  + 二级索引分区键名称
  + 二级索引排序键名称
  + 任意用户指定的投影属性的名称（仅适用于本地二级索引） 

### 保留字和特殊字符
<a name="HowItWorks.NamingRules.Reserved"></a>

DynamoDB 具有保留字和特殊字符的列表。有关完整列表，请参阅[DynamoDB 中的保留字](ReservedWords.md)。此外，以下字符在 DynamoDB 中具有特殊含义：**\$1**（哈希）和 **:**（冒号）。

尽管 DynamoDB 允许您将这些保留字和特殊字符用于名称，但我们建议您避免这样做，因为在表达式中使用这些名称时必须定义占位符变量。有关更多信息，请参阅 [DynamoDB 中的表达式属性名称（别名）](Expressions.ExpressionAttributeNames.md)。

## 数据类型
<a name="HowItWorks.DataTypes"></a>

DynamoDB 对表中的属性支持很多不同的数据类型。可按以下方式为属性分类：
+ **标量类型** - 标量类型可准确地表示一个值。标量类型包括数字、字符串、二进制、布尔值和 null。
+ **文档类型** - 文档类型可表示具有嵌套属性的复杂结构，例如您将在 JSON 文档中找到的内容。文档类型包括列表和映射。
+ **集类型** - 集类型可表示多个标量值。集类型包括字符串集、数字集和二进制集。

当您创建表或二级索引时，您必须指定每个主键属性（分区键和排序键）的名称和数据类型。此外，每个主键属性必须定义为字符串、数字或二进制类型。

DynamoDB 是 NoSQL 数据库并且*无架构*。这意味着，与主键属性不同，您无需在创建表时定义任何属性或数据类型。与此相对，关系数据库要求您在创建表时定义每个列的名称和数据类型。

下面是每种数据类型的说明以及采用 JSON 格式的示例。

### 标量类型
<a name="HowItWorks.DataTypes.Scalar"></a>

标量类型包括数字、字符串、二进制、布尔值和 null。

#### 数字
<a name="HowItWorks.DataTypes.Number"></a>

数字可为正数、负数或零。数字最多可精确到 38 位。超过此位数将导致异常。如果您需要 38 位以上的精度，可以使用字符串。
+ 正数范围：1E-130 到 9.9999999999999999999999999999999999999E\$1125
+ 负数范围：-9.9999999999999999999999999999999999999E\$1125 到 -1E-130

在 DynamoDB 中，数字以可变长度形式表示。系统会删减开头和结尾的 0。

所有数字将作为字符串通过网络发送到 DynamoDB，以最大程度地提高不同语言和库之间的兼容性。但是，DynamoDB 会将它们视为数字类型属性以方便数学运算。

您可以使用数字数据类型表示日期或时间戳。执行此操作的一种方法是使用纪元时间，自 1970 年 1 月 1 日 00:00:00 UTC 以来的秒数。例如，纪元时间 `1437136300` 表示 2015 年 7 月 17 日下午 12:31:40 UTC。

有关更多信息，请访问 [http://en.wikipedia.org/wiki/Unix\$1time](http://en.wikipedia.org/wiki/Unix_time)。

#### 字符串
<a name="HowItWorks.DataTypes.String"></a>

字符串是使用 UTF-8 二进制编码的 Unicode。如果属性未用作索引或表的键，并且受最大 DynamoDB 项目大小限制 400 KB 的约束，则字符串的最小长度可以为零。

以下附加约束将适用于定义为字符串类型的主键属性：
+ 对于简单的主键，第一个属性值（分区键）的最大长度为 2048 字节。
+ 对于复合主键，第二个属性值（排序键）的最大长度为 1024 字节。

DynamoDB 使用基础的 UTF-8 字符串编码字节整理和比较字符串。例如，“`a`”(0x61) 大于“`A`”(0x41)，“`¿`”(0xC2BF) 大于“`z`”(0x7A)。

您可使用字符串数据类型表示日期或时间戳。执行此操作的一种方法是使用 ISO 8601 字符串，如以下示例所示：
+ `2016-02-15`
+ `2015-12-21T17:42:34Z`
+ `20150311T122706Z`

有关更多信息，请访问 [http://en.wikipedia.org/wiki/ISO\$18601](http://en.wikipedia.org/wiki/ISO_8601)。

**注意**  
与传统关系数据库不同，DynamoDB 本身不支持日期和时间数据类型。相反，使用 Unix 纪元时间将日期和时间数据存储为数字数据类型可能很有用。

#### 二进制
<a name="HowItWorks.DataTypes.Binary"></a>

二进制类型属性可以存储任意二进制数据，如压缩文本、加密数据或图像。DynamoDB 会在比较二进制值时将二进制数据的每个字节视为无符号。

如果二进制属性未用作索引或表的键，且受到最大 DynamoDB 项目大小限制 400 KB 的约束，则该属性的长度可以为零。

如果您将主键属性定义为二进制类型属性，以下附加限制将适用：
+ 对于简单的主键，第一个属性值（分区键）的最大长度为 2048 字节。
+ 对于复合主键，第二个属性值（排序键）的最大长度为 1024 字节。

在将二进制值发送到 DynamoDB 之前，您的应用程序必须采用 Base64 编码格式对其进行编码。收到这些值后，DynamoDB 会将数据解码为无符号字节数组，将其用作二进制属性的长度。

下面的示例是一个采用 Base64 编码文本的二进制属性。

```
dGhpcyB0ZXh0IGlzIGJhc2U2NC1lbmNvZGVk
```

#### 布尔值
<a name="HowItWorks.DataTypes.Boolean"></a>

布尔类型属性可以存储 `true` 或 `false`。

#### Null
<a name="HowItWorks.DataTypes.Null"></a>

空代表属性具有未知或未定义状态。

### 文档类型
<a name="HowItWorks.DataTypes.Document"></a>

文档类型包括列表和映射。这些数据类型可以互相嵌套，用来表示深度最多为 32 层的复杂数据结构。

只要包含值的项目大小在 DynamoDB 项目大小限制 (400 KB) 内，列表或映射中值的数量就没有限制。

 如果属性未用于表或索引键，属性值可以是空字符串或空二进制值。属性值不能为空集（字符串集、数字集或二进制集），但允许使用空的列表和映射。列表和映射中允许使用空的字符串和二进制值。有关更多信息，请参阅 [属性](Constraints.md#limits-attributes)。

#### 列表
<a name="HowItWorks.DataTypes.Document.List"></a>

列表类型属性可存储值的有序集合。列表用方括号括起：`[ ... ]`

列表类似于 JSON 数组。列表元素中可以存储的数据类型没有限制，列表元素中的元素也不一定为相同类型。

以下示例显示了包含两个字符串和一个数字的列表。

```
FavoriteThings: ["Cookies", "Coffee", 3.14159]
```

**注意**  
DynamoDB 让您可以使用列表中的单个元素，即使这些元素深层嵌套也是如此。有关更多信息，请参阅 [在 DynamoDB 中使用表达式](Expressions.md)。

#### Map
<a name="HowItWorks.DataTypes.Document.Map"></a>

映射类型属性可以存储名称/值对的无序集合。映射用大括号括起：`{ ... }`

映射类似于 JSON 对象。映射元素中可以存储的数据类型没有限制，映射中的元素也不一定为相同类型。

映射非常适合用来将 JSON 文档存储在 DynamoDB 中。以下示例显示了一个映射，该映射包含一个字符串、一个数字和一个含有另一个映射的嵌套列表。

```
{
    Day: "Monday",
    UnreadEmails: 42,
    ItemsOnMyDesk: [
        "Coffee Cup",
        "Telephone",
        {
            Pens: { Quantity : 3},
            Pencils: { Quantity : 2},
            Erasers: { Quantity : 1}
        }
    ]
}
```

**注意**  
DynamoDB 让您可以使用映射中的单个元素，即使这些元素深层嵌套也是如此。有关更多信息，请参阅 [在 DynamoDB 中使用表达式](Expressions.md)。

### 集
<a name="HowItWorks.DataTypes.SetTypes"></a>

DynamoDB 支持表示数字、字符串或二进制值集的类型。集中的所有元素必须为相同类型。例如，数字集只能包含数字，字符串集只能包含字符串。

只要包含值的项目大小在 DynamoDB 项目大小限制 (400 KB) 内，集中的值的数量就没有限制。

集中的每个值必须是唯一的。集中的值的顺序不会保留。因此，您的应用程序不能依赖集中的元素的任何特定顺序。DynamoDB 不支持空集，但集合中允许使用空字符串和二进制值。

以下示例显示了一个字符串集、一个数字集和一个二进制集：

```
["Black", "Green", "Red"]

[42.2, -19, 7.5, 3.14]

["U3Vubnk=", "UmFpbnk=", "U25vd3k="]
```

## 数据类型描述符
<a name="HowItWorks.DataTypeDescriptors"></a>

低级别 DynamoDB API 协议使用*数据类型描述符*作为令牌，这些令牌告诉 DynamoDB 如何解释每个属性。

以下是 DynamoDB 数据类型描述符的完整列表：
+ **`S`** – String
+ **`N`** – Number
+ **`B`** – Binary
+ **`BOOL`** – Boolean
+ **`NULL`** – Null
+ **`M`** – Map
+ **`L`** – List
+ **`SS`** – String Set
+ **`NS`** – Number Set
+ **`BS`** – Binary Set

# DynamoDB 表类
<a name="HowItWorks.TableClasses"></a>

DynamoDB 提供两个表类别，旨在帮助您优化成本。“DynamoDB 标准”表类别是默认设置，建议用于绝大多数工作负载。“DynamoDB 标准-不经常访问 (DynamoDB Standard-IA)”表类别针对存储占据主要成本的表进行优化。例如，存储不经常访问数据的表（例如应用程序日志、旧的社交媒体帖子、电子商务订单历史记录以及过去的游戏成就）就适合使用 Standard-IA 表类别。请参阅 [Amazon DynamoDB 定价](https://aws.amazon.com/dynamodb/pricing/on-demand/)了解定价详细信息。

每个 DynamoDB 表都与一个表类相关联（默认是 DynamoDB 标准）。与该表关联的所有二级索引都使用相同的表类。每个表类都为数据存储以及读取和写入请求提供不同的定价。您可以根据表的存储和吞吐量使用模式，为表选择最具成本效益的表类别。

表类别的选择不是永久性的—您可以使用 AWS 管理控制台、AWS CLI 或 AWS SDK 更改此设置。DynamoDB 还支持使用面向单区域表和全局表的 AWS CloudFormation 管理表类别。要详细了解有关选择表类别的更多信息，请参阅 [在 DynamoDB 中选择表类时的注意事项](WorkingWithTables.tableclasses.md)。

# DynamoDB 中的分区和数据分布
<a name="HowItWorks.Partitions"></a>

Amazon DynamoDB 将数据存储在分区。*分区*是为表格分配的存储，由固态硬盘 (SSD) 提供支持，并可在 AWS 区域内的多个可用区中自动进行复制。分区管理由 DynamoDB 全权负责，您从不需要亲自管理分区。

在您创建表时，表的初始状态为 `CREATING`。在此期间，DynamoDB 会向表分配足够的分区，以便满足预调配吞吐量需求。表的状态变为 `ACTIVE` 后，您可开始读取和写入表数据。

在以下情况下，DynamoDB 会向表分配额外的分区：
+ 您增加的表的预调配吞吐量设置超出了现有分区的支持能力。
+ 现有分区填充已达到容量上限，并且需要更多的存储空间。

分区管理在后台自动进行，对程序是透明的。您的表将保留可用吞吐量并完全支持预调配吞吐量需求。

有关更多详细信息，请参阅[分区键设计](bp-partition-key-design.md)。

DynamoDB 中的全局二级索引还包含分区。全局二级索引中的数据将与其基表中的数据分开存储，但索引分区与表分区的行为方式几乎相同。

## 数据分布：分区键
<a name="HowItWorks.Partitions.SimpleKey"></a>

如果表具有简单主键（只有分区键），DynamoDB 将根据其分区键值存储和检索各个项目。

DynamoDB 使用分区键的值作为内部散列函数的输入值，从而将项目写入表中。散列函数的输出值决定了项目将要存储在哪个分区。

要从表读取项目，必须指定项目的分区键值。DynamoDB 使用此值作为其哈希函数的输入值，得到可从中找到该项目的分区。

下图显示了名为 *Pets* 的表，该表跨多个分区。表的主键是 *AnimalType*（仅显示此关键属性）。DynamoDB 使用其哈希函数决定新项目的存储位置，在这种情况下，会根据字符串 *Dog* 的哈希值。请注意，项目并非按排序顺序存储的。每个项目的位置由其分区键的哈希值决定。

![\[DynamoDB 根据分区键的哈希值在分区之间分配表项目的情况。\]](http://docs.aws.amazon.com/zh_cn/amazondynamodb/latest/developerguide/images/HowItWorksPartitionKey.png)


**注意**  
DynamoDB 经过优化，不论表有多少个分区，都可在这些分区上统一分配项目。我们建议您选择具有较多非重复值（相对于表中的项目数）的分区键。

## 数据分布：分区键和排序键
<a name="HowItWorks.Partitions.CompositeKey"></a>

如果表具有复合主键（分区键和排序键），DynamoDB 将采用与 [数据分布：分区键](#HowItWorks.Partitions.SimpleKey) 中所述的方式相同的方式来计算分区键的哈希值。但是，它倾向于将具有相同分区键值的项目保留在一起，并按排序键属性的值排序。具有相同分区键值的一组项目称为项目集。对项目集进行了优化，可以有效地检索项目集中的项目范围。如果您的表没有本地二级索引，DynamoDB 将根据需要自动将您的项目集拆分到任意数量的分区中，以存储数据并提供读写吞吐量。

为将某个项目写入表中，DynamoDB 会计算分区键的散列值以确定该项目的存储分区。在该分区中，可能有几个具有相同分区键值的项目。因此，DynamoDB 会按排序键的升序将该项目存储在具有相同分区键的其他项目中。

要从表中读取项目，必须指定分区键值和排序键值。DynamoDB 计算分区键的哈希值，得出可从中找到该项目的分区。

如果您想要的项目具有相同的分区键值，则可以通过单一操作 (`Query`) 读取表中的多个项目。DynamoDB 返回具有该分区键值的所有项目。或者，您也可以对排序键应用某个条件，以便它仅返回特定值范围内的项目。

假设 *Pets* 表具有由 *AnimalType*（分区键）和 *Name*（排序键）构成的复合主键。下图显示了 DynamoDB 写入项目的过程，分区键值为 *Dog*、排序键值为 *Fido*。

![\[DynamoDB 使用复合分区键存储项目，并使用排序键属性的值对该项目进行排序。\]](http://docs.aws.amazon.com/zh_cn/amazondynamodb/latest/developerguide/images/HowItWorksPartitionKeySortKey.png)


为读取 *Pets* 表中的同一项目，DynamoDB 会计算 *Dog* 的哈希值，从而生成这些项目的存储分区。然后，DynamoDB 扫描排序键属性值，直到找到 *Fido*。

要读取 *AnimalType* 为 *Dog* 的所有项目，您可以执行 `Query` 操作，无需指定排序键条件。默认情况下，这些项目会按存储顺序 (即按排序键的升序) 返回。或者，您也可以请求以降序返回。

若要仅查询某些 *Dog* 项目，您可以对排序键应用某个条件（例如，仅使用 *Name* 以 `A` 到 `K` 范围的字母开始的 *Dog* 项目。

**注意**  
在 DynamoDB 表中，每个分区键值的非重复排序键值无数量上限。如果要在 *Pets* 表中存储数十亿 *Dog* 项目，DynamoDB 会分配足够的存储空间来自动处理此要求。

# 了解如何从 SQL 转向 NoSQL
<a name="SQLtoNoSQL"></a>

如果您是应用程序开发人员，则可能在使用关系数据库管理系统 (RDBMS) 和结构化查询语言 (SQL) 方面有一些经验。在您开始使用 Amazon DynamoDB 时，您既会遇到许多相似之处，也会遇到许多不同之处。*NoSQL* 是一个术语，用于描述高度可用的、可扩展的并且已针对高性能进行优化的非关系数据库系统。有别于关系模型，NoSQL 数据库（如 DynamoDB）使用替代模型进行数据管理，例如键-值对或文档存储。有关更多信息，请参阅 [NoSQL 是什么?](https://aws.amazon.com/nosql)。

Amazon DynamoDB 支持 [PartiQL](https://partiql.org/)，后者一种与 SQL 兼容的开源查询语言，使您可以轻松、高效地查询数据，无论数据存储在何处或以何种格式存储。使用 PartiQL，您可以轻松处理关系数据库中的结构化数据、采用开放数据格式的半结构化和嵌套数据，甚至可以处理允许不同行中使用不同属性的 NoSQL 或文档数据库中的无模式数据。有关更多信息，请参阅 [PartiQL 查询语言](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.html)。

下节介绍常见数据库任务，并将 SQL 语句与其等效 DynamoDB 操作进行比较和对比。

**注意**  
本部分中的 SQL 示例可与 MySQL RDBMS 兼容。  
本节中的 DynamoDB 示例显示 DynamoDB 操作的名称以及该操作的参数（采用 JSON 格式）。

**Topics**
+ [在关系（SQL）和 NoSQL 之间进行选择](SQLtoNoSQL.WhyDynamoDB.md)
+ [关系（SQL）数据库和 DynamoDB 在访问方式方面的差异](SQLtoNoSQL.Accessing.md)
+ [关系（SQL）数据库和 DynamoDB 在创建表方面的差异](SQLtoNoSQL.CreateTable.md)
+ [从关系（SQL）数据库与从 DynamoDB 获取表信息方面的差异](SQLtoNoSQL.GetTableInfo.md)
+ [关系（SQL）数据库和 DynamoDB 在向表写入数据方面的差异](SQLtoNoSQL.WriteData.md)
+ [关系（SQL）数据库和 DynamoDB 在从表中读取数据方面的差异](SQLtoNoSQL.ReadData.md)
+ [关系（SQL）数据库和 DynamoDB 在管理索引方面的差异](SQLtoNoSQL.Indexes.md)
+ [关系（SQL）数据库和 DynamoDB 在修改表中的数据方面的差异](SQLtoNoSQL.UpdateData.md)
+ [关系（SQL）数据库和 DynamoDB 在从表中删除数据方面的差异](SQLtoNoSQL.DeleteData.md)
+ [关系（SQL）数据库和 DynamoDB 在删除表方面的差异](SQLtoNoSQL.RemoveTable.md)

# 在关系（SQL）和 NoSQL 之间进行选择
<a name="SQLtoNoSQL.WhyDynamoDB"></a>

如今，应用程序的要求比以往更严苛。例如，在线游戏一开始时只有几个用户和极少数据。但是，如果游戏获得成功，则可以轻松超过基础数据库管理系统的资源。基于 Web 的应用程序拥有数百、数千或数百万并发用户，并且每天生成数 TB 或更多新数据，这并不少见。此类应用程序的数据库必须每秒处理数万或数十万次读取和写入。

Amazon DynamoDB 非常适合这些类型的工作负载。作为开发人员，您首先可以使用较低的使用率，然后随着应用程序变得越来越受欢迎而逐渐增加使用率。DynamoDB 无缝扩展以处理大量数据和大量用户。

有关传统关系数据库建模以及如何使其适用于 DynamoDB 的更多信息，请参阅[在 DynamoDB 中建模关系数据的最佳实践](bp-relational-modeling.md)。

下表显示了关系数据库管理系统（RDBMS）和 DynamoDB 之间的一些高级差异。


****  

| 特征 | 关系数据库管理系统（RDBMS） | Amazon DynamoDB | 
| --- | --- | --- | 
| 最佳工作负载 | 临时查询；数据仓库；OLAP (联机分析处理)。 | Web 规模级应用程序，包括社交网络、游戏、媒体共享和物联网 (IoT)。 | 
| 数据模型 | 关系模型需要一个明确定义的架构，其中，数据将标准化为表、列和行。此外，在表、列、索引和其他数据库元素之间定义所有关系。 | DynamoDB 无架构。每个表必须具有一个用来唯一标识每个数据项目的主键，但对其他非键属性没有类似的约束。DynamoDB 可以管理结构化或半结构化数据，包括 JSON 文档。 | 
| 数据访问 | SQL 是存储和检索数据的标准。关系数据库提供一组丰富的工具来简化数据库驱动型应用程序的开发，但所有这些工具都使用 SQL。 | 您可以使用 AWS 管理控制台、AWS CLI 或 NoSQL WorkBench 来操作 DynamoDB 并执行临时任务。[PartiQL](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.html) 是一种与 SQL 兼容的查询语言，它使您能够在 DynamoDB 中选择、插入、更新和输出数据。应用程序可以使用 AWS 开发工具包 (SDK)，通过基于对象的、以文档为中心的或低级别的接口来操作 DynamoDB。 | 
| 性能： | 关系数据库已针对存储进行优化，因此，性能通常取决于磁盘子系统。开发人员和数据库管理员必须优化查询、索引和表结构以实现最高性能。 | DynamoDB 已针对计算进行优化，因此，性能主要取决于基础硬件和网络延迟。作为一项托管服务，DynamoDB 可使您和您的应用程序免受这些实施详细信息的影响，以便您能够专注于设计和构建可靠的、高性能的应用程序。 | 
| 扩展 | 利用更快的硬件进行向上扩展是最轻松的。此外，数据库表可以跨越分布式系统中的多个主机，只不过这需要额外的投资。关系数据库设定了文件数和文件大小的最大值，这将对可扩展性施加上限。 | DynamoDB 设计为使用硬件的分布式集群来向外扩展。此设计可提高吞吐量而不会增加延迟。客户指定其吞吐量要求，DynamoDB 会分配足够的资源来满足这些要求。对于每个表的项目数和表的总大小都不施加上限。 | 

# 关系（SQL）数据库和 DynamoDB 在访问方式方面的差异
<a name="SQLtoNoSQL.Accessing"></a>

要让您的应用程序能够访问数据库，其必须经过*身份验证*，以确保该应用程序能够使用数据库。此外，您的应用程序还必须获得*授权*，以使该应用程序只能执行它有权执行的操作。

下图说明客户端与关系数据库和 Amazon DynamoDB 之间的交互。

![\[与关系数据库和 NoSQL 数据库的交互。\]](http://docs.aws.amazon.com/zh_cn/amazondynamodb/latest/developerguide/images/SQLtoNoSQL.png)


下表包含有关客户端交互任务的更多详细信息。


****  

| 特征 | 关系数据库管理系统（RDBMS） | Amazon DynamoDB | 
| --- | --- | --- | 
| 用于访问数据库的工具 |  大多数关系数据库提供了命令行界面 (CLI)，以便您能够输入临时 SQL 语句并立即查看结果。  | 大多数情况下，您将编写应用程序代码。此外，您还可以使用 AWS 管理控制台、AWS Command Line Interface (AWS CLI) 或 NoSQL 向 DynamoDB 发送临时请求并查看结果。[PartiQL](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.html) 是一种与 SQL 兼容的查询语言，它使您能够在 DynamoDB 中选择、插入、更新和输出数据。 | 
| 连接到数据库 | 应用程序会建立和维护与数据库的网络连接。当应用程序完成时，它将终止连接。 | DynamoDB 是一项 Web 服务，与其进行的交互是无状态的。应用程序不需要维护持久性网络连接。相反，与 DynamoDB 的交互是通过 HTTP(S) 请求和响应进行的。 | 
| 身份验证 | 应用程序在经过身份验证之前无法连接到数据库。RDBMS 可自行执行身份验证，也可以将该任务分载到主机操作系统或目录服务。 | 对 DynamoDB 发出的每个请求均必须附有一个加密签名，此签名将对特殊请求进行身份验证。AWS SDK 提供了创建签名和签署请求所需的所有逻辑。有关更多信息，请参阅《AWS 一般参考》中的[签署 AWS API 请求](https://docs.aws.amazon.com/general/latest/gr/signing_aws_api_requests.html)。 | 
| Authorization\$1 | 应用程序只能执行自身获得授权的操作。数据库管理员或应用程序所有者可以使用 SQL GRANT 和 REVOKE 语句来控制对数据库对象 (如表) 、数据 (如表中的行) 或发出某些 SQL 语句的功能的访问权。 | 在 DynamoDB 中，由 AWS Identity and Access Management (IAM) 处理授权。您可以编写 IAM policy 来授予针对 DynamoDB 资源（如表）的权限，然后允许用户和角色使用该策略。IAM 还具有针对 DynamoDB 表中各个数据项的精细访问控制功能。有关更多信息，请参阅 [适用于 Amazon DynamoDB 的 Identity and Access Management](security-iam.md)。 | 
| 发送请求 | 应用程序为要执行的每个数据库操作发出一个 SQL 语句。收到 SQL 语句后，RDBMS 将检查其语法，创建执行操作的计划，然后执行该计划。 | 应用程序将 HTTP(S) 请求发送到 DynamoDB。该请求包含要执行的 DynamoDB 操作的名称和参数。DynamoDB 立即运行请求。 | 
| 接收响应 | RDBMS 返回来自 SQL 语句的结构。如果出错，RDBMS 将返回错误状态和消息。 | DynamoDB 返回一个包含操作结果的 HTTP(S) 响应。如果出错，DynamoDB 将返回 HTTP 错误状态和消息。 | 

# 关系（SQL）数据库和 DynamoDB 在创建表方面的差异
<a name="SQLtoNoSQL.CreateTable"></a>

表是关系数据库和 Amazon DynamoDB 中的基本数据结构。关系数据库管理系统 (RDBMS) 要求您在创建表时定义表的架构。相比之下，DynamoDB 表没有架构—与主键不同，您在创建表时无需定义任何属性或数据类型。

以下章节将使用 SQL 创建表的方式与使用 DynamoDB 创建表的方式进行了比较。

**Topics**
+ [使用 SQL 创建表](#SQLtoNoSQL.CreateTable.SQL)
+ [使用 DynamoDB 创建表](#SQLtoNoSQL.CreateTable.DynamoDB)

## 使用 SQL 创建表
<a name="SQLtoNoSQL.CreateTable.SQL"></a>

通过 SQL，您将使用 `CREATE TABLE` 语句创建表，如以下示例所示。

```
CREATE TABLE Music (
    Artist VARCHAR(20) NOT NULL,
    SongTitle VARCHAR(30) NOT NULL,
    AlbumTitle VARCHAR(25),
    Year INT,
    Price FLOAT,
    Genre VARCHAR(10),
    Tags TEXT,
    PRIMARY KEY(Artist, SongTitle)
);
```

此表的主键包含 *Artist* 和 *SongTitle*。

您必须定义表的所有列和数据类型以及表的主键。(如有必要，您稍后可以使用 `ALTER TABLE` 语句更改这些定义。)

许多 SQL 实现可让您将表的存储规范定义为 `CREATE TABLE` 语句的一部分。除非另外指明，否则使用默认存储设置创建表。在生产环境中，数据库管理员可以帮助确定最佳存储参数。

## 使用 DynamoDB 创建表
<a name="SQLtoNoSQL.CreateTable.DynamoDB"></a>

使用 `CreateTable` 操作可创建预调配的模式表，同时指定参数，如下所示：

```
{
    TableName : "Music",
    KeySchema: [
        {
            AttributeName: "Artist",
            KeyType: "HASH" //Partition key
        },
        {
            AttributeName: "SongTitle",
            KeyType: "RANGE" //Sort key
        }
    ],
    AttributeDefinitions: [
        {
            AttributeName: "Artist",
            AttributeType: "S"
        },
        {
            AttributeName: "SongTitle",
            AttributeType: "S"
        }
    ],
    ProvisionedThroughput: {       // Only specified if using provisioned mode
        ReadCapacityUnits: 1,
        WriteCapacityUnits: 1
    }
}
```

此表的主键包括 *Artist*（分区键）和 *SongTitle*（排序键）。

您必须向 `CreateTable` 提供以下参数：
+ `TableName` – 表名称。
+ `KeySchema` – 用于主键的属性。有关更多信息，请参阅[表、项目和属性](HowItWorks.CoreComponents.md#HowItWorks.CoreComponents.TablesItemsAttributes)和[主键](HowItWorks.CoreComponents.md#HowItWorks.CoreComponents.PrimaryKey)。
+ `AttributeDefinitions` – 键架构属性的数据类型。
+ `ProvisionedThroughput (for provisioned tables)` – 每秒需对此表执行的读取和写入次数。DynamoDB 将保留足量的存储和系统资源，以便始终满足您的吞吐量需求。如有必要，您稍后可使用 `UpdateTable` 操作后更改这些设置。由于存储分配完全由 DynamoDB 管理，因此您无需指定表的存储要求。

# 从关系（SQL）数据库与从 DynamoDB 获取表信息方面的差异
<a name="SQLtoNoSQL.GetTableInfo"></a>

您可以根据您的规范验证是否已创建表。关系数据库中显示了所有表的架构。Amazon DynamoDB 表没有架构，因此仅显示主键属性。

**Topics**
+ [使用 SQL 获取有关表的信息](#SQLtoNoSQL.GetTableInfo.SQL)
+ [在 DynamoDB 中获取有关表的信息](#SQLtoNoSQL.GetTableInfo.DynamoDB)

## 使用 SQL 获取有关表的信息
<a name="SQLtoNoSQL.GetTableInfo.SQL"></a>

大多数关系数据库管理系统 (RDBMS) 允许您描述表的结构—列、数据类型、主键定义等。在 SQL 中，没有执行此任务的标准方法。不过，许多数据库系统提供了 `DESCRIBE` 命令。以下是 MySQL 的一个示例。

```
DESCRIBE Music;
```

这将返回表的结构以及所有列名称、数据类型和大小。

```
+------------+-------------+------+-----+---------+-------+
| Field      | Type        | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| Artist     | varchar(20) | NO   | PRI | NULL    |       |
| SongTitle  | varchar(30) | NO   | PRI | NULL    |       |
| AlbumTitle | varchar(25) | YES  |     | NULL    |       |
| Year       | int(11)     | YES  |     | NULL    |       |
| Price      | float       | YES  |     | NULL    |       |
| Genre      | varchar(10) | YES  |     | NULL    |       |
| Tags       | text        | YES  |     | NULL    |       |
+------------+-------------+------+-----+---------+-------+
```

此表的主键包含 *Artist* 和 *SongTitle*。

## 在 DynamoDB 中获取有关表的信息
<a name="SQLtoNoSQL.GetTableInfo.DynamoDB"></a>

DynamoDB 具有与之类似的 `DescribeTable` 操作。唯一的参数是表名称。

```
{
    TableName : "Music"
}
```

来自 `DescribeTable` 的回复如下所示。

```
{
  "Table": {
    "AttributeDefinitions": [
      {
        "AttributeName": "Artist",
        "AttributeType": "S"
      },
      {
        "AttributeName": "SongTitle",
        "AttributeType": "S"
      }
    ],
    "TableName": "Music",
    "KeySchema": [
      {
        "AttributeName": "Artist",
        "KeyType": "HASH"  //Partition key
      },
      {
        "AttributeName": "SongTitle",
        "KeyType": "RANGE"  //Sort key
      }
    ],

    ...
```

`DescribeTable` 还返回有关表中的索引、预置的吞吐量设置、大约项目数和其他元数据的信息。

# 关系（SQL）数据库和 DynamoDB 在向表写入数据方面的差异
<a name="SQLtoNoSQL.WriteData"></a>

关系数据库表包含数据*行*。行由*列*组成。Amazon DynamoDB 表包含*项目*。项目由*属性* 组成。

本节介绍如何将一行（或一个项目）写入表。

**Topics**
+ [使用 SQL 将数据写入表](#SQLtoNoSQL.WriteData.SQL)
+ [在 DynamoDB 中将数据写入表](#SQLtoNoSQL.WriteData.DynamoDB)

## 使用 SQL 将数据写入表
<a name="SQLtoNoSQL.WriteData.SQL"></a>

关系数据库中的表是一个由行和列组成的二维数据结构。一些数据库管理系统还支持半结构化数据（通常包括原生 JSON 或 XML 数据类型）。但实施详情因供应商而异。

在 SQL 中，您将使用 `INSERT` 语句向表添加行。

```
INSERT INTO Music
    (Artist, SongTitle, AlbumTitle,
    Year, Price, Genre,
    Tags)
VALUES(
    'No One You Know', 'Call Me Today', 'Somewhat Famous',
    2015, 2.14, 'Country',
    '{"Composers": ["Smith", "Jones", "Davis"],"LengthInSeconds": 214}'
);
```

此表的主键包含 *Artist* 和 *SongTitle*。您必须为这些列指定值。

**注意**  
该示例使用 *Tags* 列存储有关 *Music* 表中歌曲的半结构化数据。*Tags* 列定义为类型 TEXT，可在 MySQL 中存储最多 65535 个字符。

## 在 DynamoDB 中将数据写入表
<a name="SQLtoNoSQL.WriteData.DynamoDB"></a>

在 Amazon DynamoDB 中，您可以使用 DynamoDB API 或 [PartiQL](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.html)（一种与 SQL 兼容的查询语言）将项目添加到表中。

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

使用 DynamoDB API，您可以使用 `PutItem` 操作向表添加项目。

```
{
    TableName: "Music",
    Item: {
        "Artist":"No One You Know",
        "SongTitle":"Call Me Today",
        "AlbumTitle":"Somewhat Famous",
        "Year": 2015,
        "Price": 2.14,
        "Genre": "Country",
        "Tags": {
            "Composers": [
                  "Smith",
                  "Jones",
                  "Davis"
            ],
            "LengthInSeconds": 214
        }
    }
}
```

此表的主键包含 *Artist* 和 *SongTitle*。您必须为这些属性指定值。

以下是要了解的有关此 `PutItem` 示例的几个关键事项：
+ DynamoDB 使用 JSON 提供对文档的原生支持。这使得 DynamoDB 非常适合存储半结构化数据，例如*标记*。您也可以从 JSON 文档中检索和操作数据。
+ 除了主键（*Artist* 和 *SongTitle*）外，*Music* 表没有任何预定义属性。
+ 大多数 SQL 数据库是面向事务的。当您发出 `INSERT` 语句时，数据修改不是永久性的，直至您发出 `COMMIT` 语句。利用 Amazon DynamoDB，当 DynamoDB 回复 HTTP 200 状态代码（`OK`）时，`PutItem` 操作的效果是永久性的。

以下是其他几个 `PutItem` 示例。

```
{
    TableName: "Music",
    Item: {
        "Artist": "No One You Know",
        "SongTitle": "My Dog Spot",
        "AlbumTitle":"Hey Now",
        "Price": 1.98,
        "Genre": "Country",
        "CriticRating": 8.4
    }
}
```

```
{
    TableName: "Music",
    Item: {
        "Artist": "No One You Know",
        "SongTitle": "Somewhere Down The Road",
        "AlbumTitle":"Somewhat Famous",
        "Genre": "Country",
        "CriticRating": 8.4,
        "Year": 1984
    }
}
```

```
{
    TableName: "Music",
    Item: {
        "Artist": "The Acme Band",
        "SongTitle": "Still In Love",
        "AlbumTitle":"The Buck Starts Here",
        "Price": 2.47,
        "Genre": "Rock",
        "PromotionInfo": {
            "RadioStationsPlaying":[
                 "KHCR", "KBQX", "WTNR", "WJJH"
            ],
            "TourDates": {
                "Seattle": "20150625",
                "Cleveland": "20150630"
            },
            "Rotation": "Heavy"
        }
    }
}
```

```
{
    TableName: "Music",
    Item: {
        "Artist": "The Acme Band",
        "SongTitle": "Look Out, World",
        "AlbumTitle":"The Buck Starts Here",
        "Price": 0.99,
        "Genre": "Rock"
    }
}
```

**注意**  
除了 `PutItem` 之外，DynamoDB 还支持使用 `BatchWriteItem` 操作同时写入多个项目。

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

使用 PartiQL，您可以通过使用 PartiQL `Insert` 语句来使用 `ExecuteStatement` 操作向表添加项目。

```
INSERT into Music value {  
    'Artist': 'No One You Know',
    'SongTitle': 'Call Me Today',
    'AlbumTitle': 'Somewhat Famous',
    'Year' : '2015',
    'Genre' : 'Acme'
}
```

此表的主键包含 *Artist* 和 *SongTitle*。您必须为这些属性指定值。

**注意**  
有关使用 `Insert` 和 `ExecuteStatement` 的代码示例，请参阅 [PartiQL for DynamoDB Insert 语句](ql-reference.insert.md)。

------

# 关系（SQL）数据库和 DynamoDB 在从表中读取数据方面的差异
<a name="SQLtoNoSQL.ReadData"></a>

利用 SQL，您可使用 `SELECT` 语句从表中检索一个或多个行。可使用 `WHERE` 子句来确定返回给您的数据。

这与使用 Amazon DynamoDB 不同，后者提供以下操作来读取数据：
+ `ExecuteStatement` 将会检索表中的单个或多个项目。`BatchExecuteStatement` 可以通过单个操作检索不同表中的多个项目。所有这些操作均使用 [PartiQL](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.html)，一种 SQL 兼容的查询语言。
+ `GetItem` – 从表中检索单个项目。这是读取单个项目的最高效方式，因为它将提供对项目物理位置的直接访问。（DynamoDB 还提供 `BatchGetItem` 操作，允许在单个操作中执行最多 100 次 `GetItem` 调用。）
+ `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` 子句确定要返回的行。

以下是 `SELECT` 语句，它从 *Music* 表中检索单个行。`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 的 `Query` 和 `Scan` 操作功能类似，这两个操作在 [查询表方面的差异](SQLtoNoSQL.ReadData.Query.md) 和 [扫描表方面的差异](SQLtoNoSQL.ReadData.Scan.md) 中介绍。

SQL `SELECT` 语句可执行表联接，这允许您同时从多个表中检索数据。在标准化数据库表的情况下，联接是最高效的，并且各个表之间的关系很明确。不过，如果您在一个 `SELECT` 语句中联接的表过多，则会影响应用程序性能。可使用数据库复制、具体化的视图或查询重写来解决此类问题。

DynamoDB 是一个非关系数据库且不支持表联接。如果您将现有应用程序从关系数据库迁移到 DynamoDB，则需要非规范化数据模型以消除联接需要。

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

使用 PartiQL，您可以通过使用 PartiQL `ExecuteStatement` 语句来使用 `Select` 操作读取表中的项目。

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

请注意，此表的主键包含 Artist 和 SongTitle。

**注意**  
 选择 PartiSQL 语句也可用于查询或扫描 DynamoDB 表

有关使用 `Select` 和 `ExecuteStatement` 的代码示例，请参阅 [PartiQL for DynamoDB 的 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` 的代码示例，请参阅 [PartiQL for DynamoDB 的 Select 语句](ql-reference.select.md)。

------

# 扫描表方面的差异
<a name="SQLtoNoSQL.ReadData.Scan"></a>

在 SQL 中，不带 `SELECT` 子句的 `WHERE` 语句将返回表中的每个行。在 Amazon DynamoDB 中，`Scan` 操作可执行相同的工作。在这两种情况下，您都可以检索所有项目或部分项目。

无论您使用的是 SQL 还是 NoSQL 数据库，都应谨慎使用扫描操作，因为它们会占用大量系统资源。有时，扫描是适合的 (例如，扫描小型表) 或不可避免的 (例如，执行数据的批量导出操作)。但通常来说，您应设计应用程序以避免执行扫描。有关更多信息，请参阅 [在 DynamoDB 中查询表](Query.md)。

**注意**  
执行批量导出还将为每个分区创建至少 1 个文件。每个文件中的所有项目都来自于该特定分区的哈希密钥空间。

**Topics**
+ [使用 SQL 扫描表](#SQLtoNoSQL.ReadData.Scan.SQL)
+ [在 DynamoDB 中扫描表](#SQLtoNoSQL.ReadData.Scan.DynamoDB)

## 使用 SQL 扫描表
<a name="SQLtoNoSQL.ReadData.Scan.SQL"></a>

使用 SQL 时，您可以在不指定 `SELECT` 子句的情况下使用 `WHERE` 语句扫描表并检索其所有数据。您可以在结果中请求一个或多个列。或者，如果您使用通配符 (\$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 或 [PartiQL](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.html)（一种与 SQL 兼容的查询语言）对表执行扫描。

------
#### [ 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，您可以通过 `Select` 语句来使用 `ExecuteStatement` 操作执行扫描，以返回表的所有内容。

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

请注意，此语句将返回 Music 表中的所有项目。

有关使用 `Select` 和 `ExecuteStatement` 的代码示例，请参阅 [PartiQL for DynamoDB 的 Select 语句](ql-reference.select.md)。

------

# 关系（SQL）数据库和 DynamoDB 在管理索引方面的差异
<a name="SQLtoNoSQL.Indexes"></a>

索引使您能够访问替代查询模式，并可以加快查询速度。本节将 SQL 和 Amazon DynamoDB 中的索引创建和使用进行了比较和对比。

无论您使用的是关系数据库还是 DynamoDB，在创建索引时都应谨慎。只要对表进行写入，就必须更新表的所有索引。在具有大型表的写入密集型环境中，这会占用大量系统资源。在只读环境或主读环境中，这算不上一个问题。但是，您应确保索引实际上由应用程序使用，而不只是占用空间。

**Topics**
+ [关系（SQL）数据库和 DynamoDB 在创建索引方面的差异](#SQLtoNoSQL.Indexes.Creating)
+ [关系（SQL）数据库和 DynamoDB 在查询和扫描索引方面的差异](#SQLtoNoSQL.Indexes.QueryAndScan)

## 关系（SQL）数据库和 DynamoDB 在创建索引方面的差异
<a name="SQLtoNoSQL.Indexes.Creating"></a>

将 SQL 中的 `CREATE INDEX` 语句与 Amazon DynamoDB 中的 `UpdateTable` 操作进行比较。

**Topics**
+ [使用 SQL 创建索引](#SQLtoNoSQL.Indexes.Creating.SQL)
+ [在 DynamoDB 中创建索引](#SQLtoNoSQL.Indexes.Creating.DynamoDB)

### 使用 SQL 创建索引
<a name="SQLtoNoSQL.Indexes.Creating.SQL"></a>

在关系数据库中，索引是一个数据结构，可让您对表中的不同的列执行快速查询。您可以使用 `CREATE INDEX` SQL 语句将索引添加到现有表，并指定要建立索引的列。在创建索引后，您可以照常查询表中的数据，但现在数据库可使用索引快速查找表中的指定行，而不是扫描整个表。

在创建一个索引后，数据库将为您维护此索引。只要您修改表中的数据，就会自动更改索引以反映表中的更改。

在 MySQL 中，您可以创建如下所示的索引。

```
CREATE INDEX GenreAndPriceIndex
ON Music (genre, price);
```

### 在 DynamoDB 中创建索引
<a name="SQLtoNoSQL.Indexes.Creating.DynamoDB"></a>

在 DynamoDB 中，您可以创建和使用*二级索引*来实现类似目的。

DynamoDB 中的索引与其关系对应项不同。当您创建二级索引时，必须指定其键属性—分区键和排序键。创建二级索引后，可以 `Query` 或 `Scan`，就像对表一样。DynamoDB 没有查询优化程序，因此仅在 `Query` 或 `Scan` 时使用二级索引。

DynamoDB 支持两种不同的索引：
+ 全局二级索引 – 索引的主键可以是其表中的任意两个属性。
+ 本地二级索引 – 索引的分区键必须与其表的分区键相同。不过，排序键可以是任何其他属性。

DynamoDB 确保二级索引中的数据最终与其表保持一致。您可以请求对表或本地二级索引执行强一致性 `Query` 或 `Scan` 操作。但是，全局二级索引仅支持最终一致性。

可以使用 `UpdateTable` 操作并指定 `GlobalSecondaryIndexUpdates`，将全局二级索引添加到现有表。

```
{
    TableName: "Music",
    AttributeDefinitions:[
        {AttributeName: "Genre", AttributeType: "S"},
        {AttributeName: "Price", AttributeType: "N"}
    ],
    GlobalSecondaryIndexUpdates: [
        {
            Create: {
                IndexName: "GenreAndPriceIndex",
                KeySchema: [
                    {AttributeName: "Genre", KeyType: "HASH"}, //Partition key
                    {AttributeName: "Price", KeyType: "RANGE"}, //Sort key
                ],
                Projection: {
                    "ProjectionType": "ALL"
                },
                ProvisionedThroughput: {                                // Only specified if using provisioned mode
                    "ReadCapacityUnits": 1,"WriteCapacityUnits": 1
                }
            }
        }
    ]
}
```

您必须向 `UpdateTable` 提供以下参数：
+ `TableName` – 索引将关联到的表。
+ `AttributeDefinitions` – 索引的键架构属性的数据类型。
+ `GlobalSecondaryIndexUpdates` – 有关要创建的索引的详细信息：
  + `IndexName` – 索引的名称。
  + `KeySchema` – 用于索引主键的属性。
  + `Projection` – 表中要复制到索引的属性。在此情况下，`ALL` 意味着复制所有属性。
  + `ProvisionedThroughput (for provisioned tables)` – 每秒需对此索引执行的读取和写入次数。(它与表的预调配吞吐量设置是分开的。) 

在此操作中，会将表中的数据回填到新索引。在回填期间，表保持可用。但索引未准备就绪，直至其 `Backfilling` 属性从 true 变为 false。您可以使用 `DescribeTable` 操作查看此属性。

## 关系（SQL）数据库和 DynamoDB 在查询和扫描索引方面的差异
<a name="SQLtoNoSQL.Indexes.QueryAndScan"></a>

将使用 SQL 中的 SELECT 语句查询并扫描索引与使用 Amazon DynamoDB 中的 `Query` 和 `Scan` 操作查询并扫描索引进行比较。

**Topics**
+ [使用 SQL 查询并扫描索引](#SQLtoNoSQL.Indexes.QueryAndScan.SQL)
+ [在 DynamoDB 中查询并扫描索引](#SQLtoNoSQL.Indexes.QueryAndScan.DynamoDB)

### 使用 SQL 查询并扫描索引
<a name="SQLtoNoSQL.Indexes.QueryAndScan.SQL"></a>

在关系数据库中，不能直接使用索引。相反，您通过发出 `SELECT` 语句来查询表，查询优化程序可使用任何索引。

*查询优化程序* 是一个关系数据库管理系统 (RDBMS) 组件，它将评估可用索引并确定是否可使用这些索引来加快查询速度。如果索引可用来加快查询速度，则 RDBMS 会先访问索引，然后使用索引查找表中的数据。

以下几个 SQL 语句可使用 *GenreAndPriceIndex* 提高性能。我们假定 *Music* 表包含足够多的数据以促使查询优化程序决定使用此索引，而不是扫描整个表。

```
/* All of the rock songs */

SELECT * FROM Music
WHERE Genre = 'Rock';
```

```
/* All of the cheap country songs */

SELECT Artist, SongTitle, Price FROM Music
WHERE Genre = 'Country' AND Price < 0.50;
```

### 在 DynamoDB 中查询并扫描索引
<a name="SQLtoNoSQL.Indexes.QueryAndScan.DynamoDB"></a>

在 DynamoDB 中，直接对索引执行 `Query` 和 `Scan` 操作，就如同对表执行此操作一样。您可以使用 DynamoDB API 或 [PartiQL](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.html)（一种与 SQL 兼容的查询语言）来查询或扫描索引。您必须指定 `TableName` 和 `IndexName`。

下面是一些 DynamoDB 中对 *GenreAndPriceIndex* 的查询。（此索引的键架构包含 *Genre* 和 *Price*。）

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

```
// All of the rock songs

{
    TableName: "Music",
    IndexName: "GenreAndPriceIndex",
    KeyConditionExpression: "Genre = :genre",
    ExpressionAttributeValues: {
        ":genre": "Rock"
    },
};
```

此示例使用 `ProjectionExpression` 指示您只希望结果中显示部分而不是全部属性。

```
// All of the cheap country songs

{
    TableName: "Music",
    IndexName: "GenreAndPriceIndex",
    KeyConditionExpression: "Genre = :genre and Price < :price",
    ExpressionAttributeValues: {
        ":genre": "Country",
        ":price": 0.50
    },
    ProjectionExpression: "Artist, SongTitle, Price"
};
```

以下是对 *GenreAndPriceIndex* 进行的扫描。

```
// Return all of the data in the index

{
    TableName:  "Music",
    IndexName: "GenreAndPriceIndex"
}
```

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

使用 PartiQL，您可以使用 `Select` 语句来对索引执行查询和扫描。

```
// All of the rock songs

SELECT * 
FROM Music.GenreAndPriceIndex
WHERE Genre = 'Rock'
```

```
// All of the cheap country songs

SELECT * 
FROM Music.GenreAndPriceIndex
WHERE Genre = 'Rock' AND Price < 0.50
```

以下是对 *GenreAndPriceIndex* 进行的扫描。

```
// Return all of the data in the index

SELECT *
FROM Music.GenreAndPriceIndex
```

**注意**  
有关使用 `Select` 的代码示例，请参阅 [PartiQL for DynamoDB 的 Select 语句](ql-reference.select.md)。

------

# 关系（SQL）数据库和 DynamoDB 在修改表中的数据方面的差异
<a name="SQLtoNoSQL.UpdateData"></a>

SQL 语言提供 `UPDATE` 语句来修改数据。Amazon DynamoDB 使用 `UpdateItem` 操作来完成类似的任务。

**Topics**
+ [使用 SQL 修改表中的数据](#SQLtoNoSQL.UpdateData.SQL)
+ [在 DynamoDB 中修改表中的数据](#SQLtoNoSQL.UpdateData.DynamoDB)

## 使用 SQL 修改表中的数据
<a name="SQLtoNoSQL.UpdateData.SQL"></a>

在 SQL 中，您将使用 `UPDATE` 语句修改一个或多个行。`SET` 子句为一个或多个列指定新值，`WHERE` 子句确定修改的行。示例如下：

```
UPDATE Music
SET RecordLabel = 'Global Records'
WHERE Artist = 'No One You Know' AND SongTitle = 'Call Me Today';
```

如果任何行均不匹配 `WHERE` 子句，则 `UPDATE` 语句不起作用。

## 在 DynamoDB 中修改表中的数据
<a name="SQLtoNoSQL.UpdateData.DynamoDB"></a>

在 DynamoDB 中，您可以使用 DynamoDB API 或 [PartiQL](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.html)（一种与 SQL 兼容的查询语言）修改单个项目。（如果要修改多个项目，则必须使用多个操作。）

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

借助 DynamoDB API，您可以使用 `UpdateItem` 操作修改单个项目。

```
{
    TableName: "Music",
    Key: {
        "Artist":"No One You Know",
        "SongTitle":"Call Me Today"
    },
    UpdateExpression: "SET RecordLabel = :label",
    ExpressionAttributeValues: {
        ":label": "Global Records"
    }
}
```

必须指定要修改的项目的 `Key` 属性和 `UpdateExpression` 才能指定属性值。`UpdateItem` 行为类似于“upsert”操作。如果表中存在该项目，则会对其进行更新，但如果不存在，则会添加（插入）一个新项目。

`UpdateItem` 支持*条件写入*，在此情况下，操作仅在特定 `ConditionExpression` 的计算结果为 true 时成功完成。例如，除非歌曲的价格大于或等于 2.00，否则以下 `UpdateItem` 操作不会执行更新。

```
{
    TableName: "Music",
    Key: {
        "Artist":"No One You Know",
        "SongTitle":"Call Me Today"
    },
    UpdateExpression: "SET RecordLabel = :label",
    ConditionExpression: "Price >= :p",
    ExpressionAttributeValues: {
        ":label": "Global Records",
        ":p": 2.00
    }
}
```

`UpdateItem` 还支持*原子计数器* 或类型为 `Number` 的属性（可递增或递减）。原子计数器在很多方面都类似于 SQL 数据库中的顺序生成器、身份列或自递增字段。

以下是一个 `UpdateItem` 操作的示例，它初始化一个新属性（*Plays*）来跟踪歌曲的已播放次数。

```
{
    TableName: "Music",
    Key: {
        "Artist":"No One You Know",
        "SongTitle":"Call Me Today"
    },
    UpdateExpression: "SET Plays = :val",
    ExpressionAttributeValues: {
        ":val": 0
    },
    ReturnValues: "UPDATED_NEW"
}
```

`ReturnValues` 参数设置为 `UPDATED_NEW`，这将返回已更新的任何属性的新值。在此示例中，它返回 0 (零)。

当某人播放此歌曲时，可使用以下 `UpdateItem` 操作来将*播放次数*增加 1。

```
{
    TableName: "Music",
    Key: {
        "Artist":"No One You Know",
        "SongTitle":"Call Me Today"
    },
    UpdateExpression: "SET Plays = Plays + :incr",
    ExpressionAttributeValues: {
        ":incr": 1
    },
    ReturnValues: "UPDATED_NEW"
}
```

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

使用 PartiQL，您可以通过使用 PartiQL `ExecuteStatement` 语句来使用 `Update` 操作修改表中的项目。

此表的主键包含 *Artist* 和 *SongTitle*。您必须为这些属性指定值。

```
UPDATE Music
SET RecordLabel ='Global Records'
WHERE Artist='No One You Know' AND SongTitle='Call Me Today'
```

如下例所示，您还可以一次修改多个字段。

```
UPDATE Music
SET RecordLabel = 'Global Records'
SET AwardsWon = 10
WHERE Artist ='No One You Know' AND SongTitle='Call Me Today'
```

`Update` 还支持*原子计数器* 或类型为 `Number` 的属性（可递增或递减）。原子计数器在很多方面都类似于 SQL 数据库中的顺序生成器、身份列或自递增字段。

以下是一个 `Update` 语句的示例，它初始化一个新属性 (*Plays*) 来跟踪歌曲的已播放次数。

```
UPDATE Music
SET Plays = 0
WHERE Artist='No One You Know' AND SongTitle='Call Me Today'
```

当某人播放此歌曲时，可使用以下 `Update` 语句来将 *Plays* 增加 1。

```
UPDATE Music
SET Plays = Plays + 1
WHERE Artist='No One You Know' AND SongTitle='Call Me Today'
```

**注意**  
有关使用 `Update` 和 `ExecuteStatement` 的代码示例，请参阅 [PartiQL for DynamoDB Update 语句](ql-reference.update.md)。

------

# 关系（SQL）数据库和 DynamoDB 在从表中删除数据方面的差异
<a name="SQLtoNoSQL.DeleteData"></a>

在 SQL 中，`DELETE` 语句从表检索一个或多个行。Amazon DynamoDB 使用 `DeleteItem` 操作一次删除一个项目。

**Topics**
+ [使用 SQL 删除表中的数据](#SQLtoNoSQL.DeleteData.SQL)
+ [在 DynamoDB 中删除表中的数据](#SQLtoNoSQL.DeleteData.DynamoDB)

## 使用 SQL 删除表中的数据
<a name="SQLtoNoSQL.DeleteData.SQL"></a>

在 SQL 中，可使用 `DELETE` 语句删除一个或多个行。`WHERE` 子句确定要修改的行。示例如下：

```
DELETE FROM Music
WHERE Artist = 'The Acme Band' AND SongTitle = 'Look Out, World';
```

您可以修改 `WHERE` 子句以删除多个行。例如，您可以删除某个特定艺术家的所有歌曲，如以下示例所示。

```
DELETE FROM Music WHERE Artist = 'The Acme Band'
```

## 在 DynamoDB 中删除表中的数据
<a name="SQLtoNoSQL.DeleteData.DynamoDB"></a>

在 DynamoDB 中，您可以使用 DynamoDB API 或 [PartiQL](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.html)（一种与 SQL 兼容的查询语言）删除单个项目。（如果要修改多个项目，则必须使用多个操作。）

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

借助 DynamoDB API，您可以使用 `DeleteItem` 操作删除表中的数据（一次删除一个项目）。您必须指定项目的主键值。

```
{
    TableName: "Music",
    Key: {
        Artist: "The Acme Band",
        SongTitle: "Look Out, World"
    }
}
```

**注意**  
除了 `DeleteItem` 之外，Amazon DynamoDB 还支持使用 `BatchWriteItem` 操作同时删除多个项目。

`DeleteItem` 支持*条件写入*，在此情况下，操作仅在特定 `ConditionExpression` 的计算结果为 true 时成功完成。例如，以下 `DeleteItem` 操作仅在项目具有 *RecordLabel* 属性时删除项目。

```
{
    TableName: "Music",
    Key: {
        Artist: "The Acme Band",
        SongTitle: "Look Out, World"
    },
   ConditionExpression: "attribute_exists(RecordLabel)"
}
```

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

使用 PartiQL，您可以使用 `Delete` 语句通过 `ExecuteStatement` 操作删除表中的数据（一次删除一个项目）。您必须指定项目的主键值。

此表的主键包含 *Artist* 和 *SongTitle*。您必须为这些属性指定值。

```
DELETE FROM Music
WHERE Artist = 'Acme Band' AND SongTitle = 'PartiQL Rocks'
```

您还可以指定操作的其他选项。以下 `DELETE` 操作只有在项目超过 11 个*奖项*时才会删除该项目。

```
DELETE FROM Music
WHERE Artist = 'Acme Band' AND SongTitle = 'PartiQL Rocks' AND Awards > 11
```

**注意**  
有关使用 `DELETE` 和 `ExecuteStatement` 的代码示例，请参阅 [PartiQL for DynamoDB Delete 语句](ql-reference.delete.md)。

------

# 关系（SQL）数据库和 DynamoDB 在删除表方面的差异
<a name="SQLtoNoSQL.RemoveTable"></a>

在 SQL 中，可使用 `DROP TABLE` 语句删除表。在 Amazon DynamoDB 中，使用 `DeleteTable` 操作。

**Topics**
+ [使用 SQL 删除表](#SQLtoNoSQL.RemoveTable.SQL)
+ [在 DynamoDB 中删除表](#SQLtoNoSQL.RemoveTable.DynamoDB)

## 使用 SQL 删除表
<a name="SQLtoNoSQL.RemoveTable.SQL"></a>

当您不再需要一个表并希望将它永久性丢弃时，您将使用 SQL 中的 `DROP TABLE` 语句。

```
DROP TABLE Music;
```

表一经删除便无法恢复。(一些关系数据库允许您撤消 `DROP TABLE` 操作，但这是一项供应商特定的功能，并未广泛实施。)

## 在 DynamoDB 中删除表
<a name="SQLtoNoSQL.RemoveTable.DynamoDB"></a>

在 DynamoDB 中，`DeleteTable` 是类似的操作。在以下示例中，表将被永久删除。

```
{
    TableName: "Music"
}
```

# Amazon DynamoDB 学习资源和工具
<a name="AdditionalResources"></a>

您可以使用以下其他资源来了解和使用 DynamoDB。

**Topics**
+ [编程和可视化工具](#AdditionalResources.Tools)
+ [规范性指导文章](#AdditionalResources.PrescriptiveGuidance)
+ [知识中心文章](#AdditionalResources.KnowledgeCenter)
+ [博客文章、存储库和指南](#AdditionalResources.Guides)
+ [数据建模和设计模式表示](#AdditionalResources.DataModeling)
+ [培训课程](#AdditionalResources.Training)

## 编程和可视化工具
<a name="AdditionalResources.Tools"></a>

您可以使用以下编码和可视化工具来使用 DynamoDB：
+ [适用于 Amazon DynamoDB 的 NoSQL Workbench](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/workbench.html) – 一款统一的可视化工具，可帮助您设计、创建、查询和管理 DynamoDB 表。它提供数据建模、数据可视化和查询开发功能。
+ [Dynobase](https://dynobase.dev/) – 一个桌面工具，便于查看 DynamoDB 表和使用这些表，创建应用程序代码，编辑记录并实时验证。
+ [DynamoDB Toolbox](https://github.com/jeremydaly/dynamodb-toolbox) – Jeremy Daly 的一个项目，提供用于处理数据建模以及 JavaScript 和 Node.js 的实用程序。
+ [DynamoDB Streams Processor](https://github.com/jeremydaly/dynamodb-streams-processor) – 一个简单的工具，您可以使用它来处理 [DynamoDB 流](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Streams.html)。

## 规范性指导文章
<a name="AdditionalResources.PrescriptiveGuidance"></a>

AWS Prescriptive Guidance 提供久经考验的策略、指南和模式，以帮助您加快项目进度。这些资源是由 AWS 技术专家和全球 AWS 合作伙伴社区根据他们多年来帮助客户实现其业务目标的经验开发的。

**数据建模和迁移**
+ [DynamoDB 中的分层数据模型](https://docs.aws.amazon.com/prescriptive-guidance/latest/dynamodb-hierarchical-data-model/introduction.html)
+ [使用 DynamoDB 对数据建模](https://docs.aws.amazon.com/prescriptive-guidance/latest/dynamodb-data-modeling/welcome.html)
+ [使用 AWS DMS 将 Oracle 数据库迁移到 DynamoDB](https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/migrate-an-oracle-database-to-amazon-dynamodb-using-aws-dms.html)

**全局表**
+ [使用 Amazon DynamoDB 全局表](https://docs.aws.amazon.com/prescriptive-guidance/latest/dynamodb-global-tables/introduction.html)

**无服务器**
+ [通过 AWS Step Functions 实现无服务器 saga 模式](https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/implement-the-serverless-saga-pattern-by-using-aws-step-functions.html)

**SaaS 架构**
+ [在单个控制面板上管理多个 SaaS 产品的租户](https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/manage-tenants-across-multiple-saas-products-on-a-single-control-plane.html)
+ [使用 C\$1 和 AWS CDK 在 SaaS 架构中为孤立模型进行租户登录](https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/tenant-onboarding-in-saas-architecture-for-the-silo-model-using-c-and-aws-cdk.html)

**数据保护和数据移动**
+ [配置对 Amazon DynamoDB 的跨账户访问](https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/configure-cross-account-access-to-amazon-dynamodb.html)
+ [DynamoDB 的完整表格复制选项](https://docs.aws.amazon.com/prescriptive-guidance/latest/dynamodb-full-table-copy-options/)
+ [ 上数据库的灾难恢复策略AWS](https://docs.aws.amazon.com/prescriptive-guidance/latest/strategy-database-disaster-recovery/)

**其他**
+ [帮助在 DynamoDB 中强制加标签](https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/help-enforce-dynamodb-tagging.html)

**规范性指导视频演练**
+ [使用无服务器架构创建数据管道](https://youtu.be/JiWHomdh1oI?)
+ [Novartis - 购买引擎：人工智能驱动的采购门户](https://youtu.be/vp8oPiHN4cA)
+ [Veritiv：利用洞察力预测 AWS 数据湖的销售需求](https://youtu.be/jg85DzUZ9Ac)
+ [mimik：利用 AWS 的混合边缘云支持边缘微服务网格](https://youtu.be/-S-R7MWRpaI)
+ [使用 Amazon DynamoDB 更改数据捕获](https://youtu.be/6YVjzD-70p4)

有关 DynamoDB 的其他规范性指导文章和视频，请参阅[规范性指导](https://tiny.amazon.com/fiui3cog/ForinternaldemoofnewpageExternalURLwillbeneededforlive)。

## 知识中心文章
<a name="AdditionalResources.KnowledgeCenter"></a>

AWS 知识中心文章和视频涵盖了我们从 AWS 客户那里收到的最常见问题和请求。以下是关于与 DynamoDB 相关的特定任务的最新知识中心文章：

**成本优化**
+ [如何使用 Amazon DynamoDB 优化成本？](https://repost.aws/knowledge-center/dynamodb-optimize-costs)

**节流和延迟**
+ [如何对 Amazon DynamoDB 表中的高延迟问题进行故障排除？](https://repost.aws/knowledge-center/dynamodb-high-latency)
+ [为什么我的 DynamoDB 表受到限制？](https://repost.aws/knowledge-center/dynamodb-table-throttled)
+ [为什么我的按需 DynamoDB 表受到限制？](https://repost.aws/knowledge-center/on-demand-table-throttling-dynamodb)

**分页**
+ [我如何在 DynamoDB 中实现分页](https://repost.aws/knowledge-center/dynamodb-implement-pagination)

**事务**
+ [为什么我的 `TransactWriteItems` API 调用在 DynamoDB 中失败了](https://repost.aws/knowledge-center/dynamodb-transactwriteitems)

**问题排查**

[]()
+ [如何解决 DynamoDB Auto Scaling 的问题？](https://repost.aws/knowledge-center/dynamodb-auto-scaling)
+ [如何排查 DynamoDB 中的 HTTP 4XX 错误](https://repost.aws/knowledge-center/usererrors-dynamodb-table)

有关 DynamoDB 的其他文章和视频，请参阅[知识中心文章](https://repost.aws/search/knowledge-center?globalSearch=dynamodb)。

## 博客文章、存储库和指南
<a name="AdditionalResources.Guides"></a>

除了 [DynamoDB 开发人员指南](Introduction.md)之外，还有许多有关使用 DynamoDB 的有用资源。以下是一些有关使用 DynamoDB 的精选博客文章、存储库和指南：
+ 采用各种 AWS 开发工具包语言的 [DynamoDB 代码示例](https://github.com/aws-samples/aws-dynamodb-examples)AWS 存储库：[Node.js](https://github.com/aws-samples/aws-dynamodb-examples/tree/master/examples/SDK/node.js)、[Java](https://github.com/aws-samples/aws-dynamodb-examples/tree/master/examples/SDK/java)、[Python](https://github.com/aws-samples/aws-dynamodb-examples/tree/master/examples/SDK/python)、[.Net](https://github.com/aws-samples/aws-dynamodb-examples/tree/master/examples/SDK/dotnet)、[Go](https://github.com/aws-samples/aws-dynamodb-examples/tree/master/examples/SDK/golang) 和 [Rust](https://github.com/aws-samples/aws-dynamodb-examples/tree/master/examples/SDK/rust)。
+ [DynamoDB 手册](https://www.dynamodbbook.com/) – 来自 [Alex DeBrie](https://twitter.com/alexbdebrie) 的综合指南，其中讲授了使用 DynamoDB 进行数据建模的策略驱动方法。
+ [DynamoDB 指南](https://www.dynamodbguide.com/) – 来自 [Alex DeBrie](https://twitter.com/alexbdebrie) 的开放指南，介绍了 DynamoDB NoSQL 数据库的基本概念和高级功能。
+ [如何通过 20 个简单步骤从 RDBMS 切换到 DynamoDB](https://www.jeremydaly.com/how-to-switch-from-rdbms-to-dynamodb-in-20-easy-steps/) – [Jeremy Daly](https://twitter.com/jeremy_daly) 提供的学习数据建模的有用步骤列表。
+ [DynamoDB JavaScript DocumentClient 小抄](https://github.com/dabit3/dynamodb-documentclient-cheat-sheet) – 帮助您在 Node.js 或 JavaScript 环境中使用 DynamoDB 构建应用程序的入门小抄。
+ [DynamoDB 核心概念视频](https://www.youtube.com/playlist?list=PLJo-rJlep0EDNtcDeHDMqsXJcuKMcrC5F) – 此播放列表涵盖了 DynamoDB 的许多核心概念。

## 数据建模和设计模式表示
<a name="AdditionalResources.DataModeling"></a>

您可以使用以下有关数据建模和设计模式的资源来帮助您充分利用 DynamoDB：
+ [AWS re:Invent 2019：使用 DynamoDB 进行数据建模](https://www.youtube.com/watch?v=DIQVJqiSUkE) 
  + [Alex DeBrie](https://twitter.com/alexbdebrie) 发表的演讲，有助于您开始了解 DynamoDB 数据建模的原理。
+ [AWS re:Invent 2020：使用 DynamoDB 进行数据建模 – 第 1 部分](https://www.youtube.com/watch?v=fiP2e-g-r4g)
+ [AWS re:Invent 2020：使用 DynamoDB 进行数据建模 – 第 2 部分](https://www.youtube.com/watch?v=0uLF1tjI_BI)
+ [AWS re:Invent 2017：高级设计模式](https://www.youtube.com/watch?v=jzeKPKpucS0)
+ [AWS re:Invent 2018：高级设计模式](https://www.youtube.com/watch?v=HaEPXoXVf2k)
+ [AWS re:Invent 2019：高级设计模式](https://www.youtube.com/watch?v=6yqfmXiZTlM)
  + Jeremy Daly 分享 [12 个要点](https://www.jeremydaly.com/takeaways-from-dynamodb-deep-dive-advanced-design-patterns-dat403/)。
+ [AWS re:Invent 2020：DynamoDB 高级设计模式 – 第 1 部分](https://www.youtube.com/watch?v=MF9a1UNOAQo&index=1)
+ [AWS re:Invent 2020：DynamoDB 高级设计模式 – 第 2 部分](https://www.youtube.com/watch?v=_KNrRdWD25M&index=2)
+ [Twitch 上的 DynamoDB 办公时间](https://amazondynamodbofficehrs.splashthat.com/)

**注意**  
每个会议涵盖不同的使用案例和示例。

## 培训课程
<a name="AdditionalResources.Training"></a>

有许多不同的培训课程和教学选项可供您进一步了解 DynamoDB。以下是一些当前的例子：
+ [使用 Amazon DynamoDB 进行开发](https://www.aws.training/Details/Curriculum?id=65583) – 由 AWS 设计，引导您从初学者成为借助 Amazon DynamoDB 数据建模开发真实应用程序的专家。
+ [DynamoDB deep dive course](https://www.pluralsight.com/courses/aws-dynamodb-deep-dive-2019)：Pluralsight 提供的课程。
+ [Amazon DynamoDB：构建 NoSQL 数据库驱动的应用程序](https://www.edx.org/course/amazon-dynamodb-building-nosql-database-driven-app) – 由 AWS 培训和认证团队编写并在 edX 上托管的课程。