

# 在 DynamoDB 中使用二级索引改进数据访问
<a name="SecondaryIndexes"></a>

Amazon DynamoDB 通过指定主键值来提供对表中项目的快速访问。但是，很多应用程序可能适合有一个或多个二级（或替代）键，以便通过主键以外的属性对数据进行高效访问。要解决此问题，您可以对表创建一个或多个二级索引，然后对这些索引发出 `Query` 或 `Scan` 请求。

*二级索引*是一种数据结构，它包含表中属性的子集以及一个支持 `Query` 操作的替代键。您可以使用 `Query` 从索引中检索数据，其方式与对表使用 `Query` 大致相同。一个表可以有多个二级索引，这样，应用程序可以访问许多不同的查询模式。

**注意**  
也可以对索引使用 `Scan`，其方式与对表使用 `Scan` 大致相同。  
[基于资源的策略](access-control-resource-based.md)目前不支持跨账户访问二级索引扫描操作。

每个二级索引关联且仅关联一个表，并从该表中获取其数据。这称为索引的*基表*。在创建索引时，您为索引定义一个替代键 (分区键和排序键)。您还可以定义要从基表*投影*或复制到索引的属性。DynamoDB 将这些属性以及基表中的主键属性一起复制到索引中。然后，您可以查询或扫描该索引，就像查询或扫描表一样。

每个二级索引都由 DynamoDB 自动维护。在基表中添加、修改或删除项目时，表上的所有索引也会更新，以反映这些更改。

DynamoDB 支持两种类型的二级索引：
+ **[全局二级索引](GSI.html) — **分区键和排序键可与基表中的这些键不同的索引。全局二级索引之所以称为“全局”，是因为索引上的查询可跨过所有分区，覆盖基表的所有数据。全局二级索引存储在其远离基表的分区空间中，并且独立于基表进行扩展。
+ **[本地二级索引](LSI.html) — **分区键与基表相同但排序键不同的索引。本地二级索引之所以称为“本地”，是因为索引的每个分区的范围都限定为具有相同分区键值的基表分区。

有关全局二级索引和本地二级索引的比较，请观看此视频。

[![AWS Videos](http://img.youtube.com/vi/https://www.youtube.com/embed/BkEu7zBWge8/0.jpg)](http://www.youtube.com/watch?v=https://www.youtube.com/embed/BkEu7zBWge8)


**Topics**
+ [在 DynamoDB 中使用全局二级索引](GSI.md)
+ [本地二级索引](LSI.md)

在确定要使用的索引类型时，应考虑应用程序的要求。下表显示了全局二级索引和本地二级索引之间的主要区别。


****  

| 特征 | 全局二级索引 | 本地二级索引 | 
| --- | --- | --- | 
| 键架构 | 全局二级索引的主键可以是简单主键（分区键）或复合主键（分区键和排序键）。 | 本地二级索引的主键必须是复合主键（分区键和排序键）。 | 
| 键属性 | 索引分区键和排序键 (如果有) 可以是字符串、数字或二进制类型的任何基表属性。 | 索引的分区键是与基表的分区键相同的属性。排序键可以是字符串、数字或二进制类型的任何基表属性。 | 
| 每个分区键值的大小限制 | 全局二级索引没有大小限制。 | 对于每个分区键值，所有索引项目的大小总和必须为 10 GB 或更小。 | 
| 在线索引操作 | 全局二级索引可以在您创建表的同时创建。您还可以向现有表中添加新的全局二级索引，或删除现有的全局二级索引。有关更多信息，请参阅 [在 DynamoDB 中管理全局二级索引](GSI.OnlineOps.md)。 | 本地二级索引在您创建表的同时创建。您不能向现有表添加本地二级索引，也不能删除已存在的任何本地二级索引。 | 
| 查询和分区 | 通过全局二级索引，可以跨所有分区查询整个表。 | 借助本地二级索引，您可以对查询中分区键值指定的单个分区进行查询。 | 
| 读取一致性 | 全局二级索引查询仅支持最终一致性。 | 查询本地二级索引时，您可以选择最终一致性或强一致性。 | 
| 预置吞吐量使用 | 每个全局二级索引都有自己的用于读取和写入活动的预置吞吐量设置。对全局二级索引执行的查询或扫描会占用索引（而非基表）的容量单位。全局二级索引更新也是如此，因为会进行表写入。与全局表关联的全局二级索引会占用写入容量单位。 | 对本地二级索引执行的查询或扫描会占用基表的读取容量单位。写入一个表时，其本地二级索引也将更新；这些更新会占用基表的写入容量单位。与全局表关联的本地二级索引会占用复制的写入容量单位。 | 
| 投影属性 | 对于全局二级索引查询或扫描，您只能请求投影到索引的属性。DynamoDB 不会从表中获取任何属性。 | 如果查询或扫描本地二级索引，可以请求未投影到索引的属性。DynamoDB 会自动从表中获取这些属性。 | 

如果要创建多个含有二级索引的表，必须按顺序执行此操作。例如，您可以创建第一个表，等待其状态变为 `ACTIVE`，创建下一个表，等待其状态变为 `ACTIVE`，依此类推。如果您尝试同时创建多个含有二级索引的表，DynamoDB 会返回 `LimitExceededException`。

每个二级索引都使用与其关联的基表相同的[表类](HowItWorks.TableClasses.html)和[容量模式](capacity-mode.md)。对于每个二级索引，必须指定以下内容：
+ 要创建的索引类型 — 全局二级索引或本地二级索引。
+ 索引的名称。索引的命名规则与表的命名规则相同，具体请参阅 [Amazon DynamoDB 中的配额](ServiceQuotas.md)。就相关联的基表而言，索引的名称必须唯一，不过，与不同的基表相关联的索引的名称可以相同。
+ 索引的键架构。索引键架构中的每个属性必须是类型为 `String`、`Number` 或 `Binary` 的顶级属性。其他数据类型，包括文档和集，均不受支持。键架构的其他要求取决于索引的类型：
  + 对于全局二级索引，分区键可以是基表的任何标量属性。排序键是可选的，也可以是基表的任何标量属性。
  + 对于本地二级索引，分区键必须与基表的分区键相同，排序键必须是非键基表属性。
+ 要从基表投影到索引中的其他属性 (如果有)。这些属性是除表键属性之外的属性，表键属性会自动投影到每个索引。您可以投影任何数据类型的属性，包括标量、文档和集。
+ 索引的预置吞吐量设置（如有必要）：
  + 对于全局二级索引，您必须指定读取和写入容量单位设置。这些预置吞吐量设置独立于基表的设置。
  + 对于本地二级索引，您无需指定读取和写入容量单位设置。对本地二级索引进行的读取和写入操作会占用其基表的预置吞吐量设置。

为获得最高的查询灵活性，您可以为每个表创建最多 20 个全局二级索引（默认配额）和最多 5 个本地二级索引。

要获取表的二级索引的详细列表，请使用 `DescribeTable` 操作。`DescribeTable` 将返回表上每个的名称、存储大小和项目计数。系统并不会实时更新这些值，但会大约每隔六个小时刷新一次。

您可以使用 `Query` 或 `Scan` 操作来访问二级索引中的数据。您必须指定您要使用的基表的名称和索引的名称、要在结果中返回的属性以及要应用的任何条件表达式或筛选条件。DynamoDB 可以按升序或降序返回结果。

删除表时，会同时删除与该表关联的全部索引。

有关最佳实践，请参阅[在 DynamoDB 中使用二级索引的最佳实践](bp-indexes.md)。