

# 序列和标识列
<a name="sequences-identity-columns"></a>

序列和标识列生成整数值，在需要紧凑或用户可读的标识符时非常有用。这些值涉及在 [`CREATE SEQUENCE`](create-sequence-syntax-support.md) 文档中描述的分配和缓存行为。

**Topics**
+ [序列操作函数](sequence-functions-syntax-support.md)
+ [标识列](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 标志。双参数格式将序列的 last\$1value 字段设置为指定的值，并将其 is\$1called 字段设置为 true，这意味着下一个 nextval 将在返回值之前使序列前进。currval 将报告的值也会设置为指定的值。在三参数格式中，is\$1called 可以设置为 true 或 false。true 与双参数格式效果相同。如果将其设置为 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 在当前事务中最近返回的值。此函数与 currval 相同（除了它不是将序列名称作为参数），它引用在当前事务中最近应用了 nextval 的任何序列。如果在当前事务中尚未调用 nextval，则调用 lastval 是错误的。此函数需要针对上次使用的序列的 USAGE 或 SELECT 权限。 | 

**警告**  
如果发出调用的事务稍后中止，则不会回收 `nextval` 获得的值以供重用。这意味着，事务中止或数据库崩溃可能会导致已分配值的序列中出现间隙。在不中止事务的情况下，也可能出现这种情况。例如，带有 `ON CONFLICT` 子句的 `INSERT` 将计算要插入的元组（包括执行任何必需的 `nextval` 调用），然后再检测到任何可能导致其遵循 `ON CONFLICT` 规则的冲突。因此，Aurora DSQL 的序列对象*不能用于获取“无间隙”序列*。  
同样，由 `setval` 所做的序列状态更改会立即对其它事务可见，并且在发出调用的事务回滚时不会撤消。

序列函数要执行操作的序列由 `regclass` 参数指定，该参数只是序列在 `pg_class` 系统目录中的 OID。但是，您不必手动查找 OID，因为 `regclass` 数据类型的输入转换器将为您完成此项工作。有关详细信息，请参阅有关 [Object Identifier Types](https://www.postgresql.org/docs/current/datatype-oid.html) 的 PostgreSQL 文档。

# 标识列
<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');
```

同样，可以在 `UPDATE` 命令中使用关键字 `DEFAULT`。

这样，在许多方面，标识列的行为类似于具有默认值的列。

列定义中的子句 `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 更好地保持一致，在这些工作负载中，标识符生成频率较低，并且需要更紧密的排序。