> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-mintlify-3a82795f.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> 表相关文档

# CREATE TABLE

export const ExperimentalBadge = () => {
  return <div className="experimentalBadge">
            <div className="experimentalIcon">
            <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path strokeWidth="1.25" d="M5.5 2H10.5" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
                <path strokeWidth="1.25" d="M9.50015 2V6.19625L13.4283 12.7425C13.4738 12.8183 13.4985 12.9049 13.4996 12.9934C13.5008 13.0818 13.4785 13.169 13.435 13.246C13.3914 13.323 13.3283 13.3871 13.2519 13.4317C13.1755 13.4764 13.0886 13.4999 13.0002 13.5H3.00015C2.91164 13.5 2.8247 13.4766 2.74822 13.432C2.67174 13.3874 2.60847 13.3233 2.56487 13.2463C2.52126 13.1693 2.49889 13.082 2.50004 12.9935C2.50119 12.905 2.52582 12.8184 2.5714 12.7425L6.50015 6.19625V2" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
                <path strokeWidth="1.25" d="M4.47656 9.56754C5.30344 9.41254 6.47656 9.47942 7.99969 10.25C10.0153 11.2707 11.4216 11.0569 12.2184 10.7282" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
        </div>
            Experimental feature. <u><a href="/docs/beta-and-experimental-features#experimental-features">Learn more.</a></u>
        </div>;
};

export const CloudNotSupportedBadge = () => {
  return <div className="cloudNotSupportedBadge">
            <div className="cloudNotSupportedIcon">
            <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path strokeWidth="1.5" d="M6.33366 12.6666L12.3739 12.6667C13.6593 12.6667 14.7073 11.6187 14.7073 10.3334C14.7073 9.04804 13.6593 8.00003 12.3739 8.00003C12.3739 8.00003 12.3337 7.66659 12.0003 7.33325M10.667 5.33322C8.00033 2.33325 4.45395 4.78537 4.14195 6.68203C2.55728 6.7627 1.29395 8.06203 1.29395 9.6667C1.29395 11.3234 2.66699 12.6666 4.00033 12.6666" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
                <path strokeWidth="1.5" d="M2.66699 14L12.0003 4.66663" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
            </svg>

        </div>
            Not supported in ClickHouse Cloud
        </div>;
};

创建一个新表。该查询可根据不同的使用场景采用多种语法形式。

默认情况下，表只会在当前服务器上创建。分布式 DDL 查询通过 `ON CLUSTER` 子句来实现，相关内容[另文说明](/zh/reference/statements/distributed-ddl)。

<div id="syntax-forms">
  ## 语法格式
</div>

<div id="with-explicit-schema">
  ### 使用显式 schema
</div>

```sql theme={null}
CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
(
    name1 [type1] [NULL|NOT NULL] [DEFAULT|MATERIALIZED|EPHEMERAL|ALIAS expr1] [COMMENT 'comment for column'] [compression_codec] [TTL expr1],
    name2 [type2] [NULL|NOT NULL] [DEFAULT|MATERIALIZED|EPHEMERAL|ALIAS expr2] [COMMENT 'comment for column'] [compression_codec] [TTL expr2],
    ...
) ENGINE = engine
  [COMMENT 'comment for table']
```

在 `db` 数据库中创建一个名为 `table_name` 的表；如果未设置 `db`，则在当前数据库中创建。该表使用括号中指定的结构和 `engine` 引擎。
表结构由列描述、二级索引、投影和约束组成。如果该引擎支持[主键](#primary-key)，则会将其标明为表引擎的参数。

最简单情况下，列描述的形式为 `name type`。示例：`RegionID UInt32`。

也可以为默认值定义表达式 (见下文) 。

如有需要，可以指定主键，其中包含一个或多个键表达式。

可以为列和表添加注释。

<div id="with-a-schema-similar-to-other-table">
  ### 使用现有表的 schema
</div>

ClickHouse 支持复制现有表的 schema 和数据。

要复制现有表的 schema：

```sql theme={null}
CREATE TABLE [IF NOT EXISTS] [db2.]table_clone AS [db.]table [ENGINE = engine]
```

这会创建一个与另一个表结构相同的表。

<div id="with-a-schema-and-data-cloned-from-another-table">
  ### 使用现有表的 schema 和数据
</div>

若要复制现有表的 schema 和数据：

```sql theme={null}
CREATE TABLE [IF NOT EXISTS] [db2.]table_clone CLONE AS [db.]table [ENGINE = engine]
```

这会创建一个与现有表具有相同 schema 和数据的表。新表创建后，`db.table` 中的所有分区都会附加到该表。换句话说，在创建时，`db.table` 的数据会被克隆到 `db2.table_clone`。该查询等同于以下内容：

```sql theme={null}
CREATE TABLE [IF NOT EXISTS] [db2.]table_clone AS [db.]table [ENGINE = engine];
ALTER TABLE [db2.]table_clone ATTACH PARTITION ALL FROM [db.]table;
```

对于这两项功能，你都可以为该表指定不同的引擎。如果未指定引擎，则默认使用与原始表 (`db.table`) 相同的引擎。

<div id="from-a-table-function">
  ### 来自表函数
</div>

```sql theme={null}
CREATE TABLE [IF NOT EXISTS] [db.]table_name AS table_function()
```

创建一个表，其结果与指定的[表函数](/zh/reference/functions/table-functions)相同。创建后的表也会像所指定的对应表函数一样工作。

<div id="from-select-query">
  ### 来自 SELECT 查询
</div>

```sql theme={null}
CREATE TABLE [IF NOT EXISTS] [db.]table_name[(name1 [type1], name2 [type2], ...)] ENGINE = engine AS SELECT ...
```

使用 `engine` 引擎创建一个表，其结构与 `SELECT` 查询结果类似，并使用 `SELECT` 的数据填充该表。你也可以显式指定列描述。

如果表已存在且指定了 `IF NOT EXISTS`，则该查询不会执行任何操作。

查询中在 `ENGINE` 子句之后还可以有其他子句。有关如何创建表的详细文档，请参阅[表引擎](/zh/reference/engines/table-engines)说明。

**示例**

```sql title="Query" theme={null}
CREATE TABLE t1 (x String) ENGINE = Memory AS SELECT 1;
SELECT x, toTypeName(x) FROM t1;
```

```text title="Response" theme={null}
┌─x─┬─toTypeName(x)─┐
│ 1 │ String        │
└───┴───────────────┘
```

<div id="null-or-not-null-modifiers">
  ## NULL 或 NOT NULL 修饰符
</div>

在列定义中，数据类型后面的 `NULL` 和 `NOT NULL` 修饰符用于控制该列是否可以为 [Nullable](/zh/reference/data-types/nullable)。

如果该类型不是 `Nullable`，并且指定了 `NULL`，则会将其视为 `Nullable`；如果指定了 `NOT NULL`，则不会。例如，`INT NULL` 等同于 `Nullable(INT)`。如果该类型本身就是 `Nullable`，再指定 `NULL` 或 `NOT NULL` 修饰符时，则会抛出异常。

另请参见 [data\_type\_default\_nullable](/zh/reference/settings/session-settings#data_type_default_nullable) 设置。

<div id="default_values">
  ## 默认值
</div>

列描述可以通过 `DEFAULT expr`、`MATERIALIZED expr` 或 `ALIAS expr` 的形式指定默认值表达式。例如：`URLDomain String DEFAULT domain(URL)`。

表达式 `expr` 是可选的。如果省略，则必须显式指定列类型，此时默认值分别为：数值列为 `0`，字符串列为 `''` (空字符串) ，数组列为 `[]` (空数组) ，日期列为 `1970-01-01`，Nullable 列为 `NULL`。

默认值列的列类型可以省略，这种情况下会根据 `expr` 的类型自动推断。例如，列 `EventDate DEFAULT toDate(EventTime)` 的类型将为日期类型。

如果同时指定了 Data type 和默认值表达式，系统会插入一个隐式类型转换函数，将表达式转换为指定类型。例如：`Hits UInt32 DEFAULT 0` 在内部会表示为 `Hits UInt32 DEFAULT toUInt32(0)`。

默认值表达式 `expr` 可以引用任意表列和常量。ClickHouse 会检查对表结构的修改不会在表达式计算中引入循环。对于 INSERT，它还会检查这些表达式是否可解析——也就是说，用于计算它们的所有列都必须已传入。

<div id="default">
  ### DEFAULT
</div>

`DEFAULT expr`

普通默认值。如果在 `INSERT` 查询中未指定此类列的值，则会根据 `expr` 计算。

示例：

```sql theme={null}
CREATE OR REPLACE TABLE test
(
    id UInt64,
    updated_at DateTime DEFAULT now(),
    updated_at_date Date DEFAULT toDate(updated_at)
)
ENGINE = MergeTree
ORDER BY id;

INSERT INTO test (id) VALUES (1);

SELECT * FROM test;
┌─id─┬──────────updated_at─┬─updated_at_date─┐
│  1 │ 2023-02-24 17:06:46 │      2023-02-24 │
└────┴─────────────────────┴─────────────────┘
```

<div id="materialized">
  ### MATERIALIZED
</div>

`MATERIALIZED expr`

物化表达式。插入行时，这类列的值会根据指定的物化表达式自动计算，不能在 `INSERT` 时显式指定。

此外，此类默认值列不会包含在 `SELECT *` 的结果中。这是为了保持这样一个不变性：`SELECT *` 的结果始终都可以通过 `INSERT` 再次插入到表中。可通过设置 `asterisk_include_materialized_columns` 禁用此行为。

示例：

```sql theme={null}
CREATE OR REPLACE TABLE test
(
    id UInt64,
    updated_at DateTime MATERIALIZED now(),
    updated_at_date Date MATERIALIZED toDate(updated_at)
)
ENGINE = MergeTree
ORDER BY id;

INSERT INTO test VALUES (1);

SELECT * FROM test;
┌─id─┐
│  1 │
└────┘

SELECT id, updated_at, updated_at_date FROM test;
┌─id─┬──────────updated_at─┬─updated_at_date─┐
│  1 │ 2023-02-24 17:08:08 │      2023-02-24 │
└────┴─────────────────────┴─────────────────┘

SELECT * FROM test SETTINGS asterisk_include_materialized_columns=1;
┌─id─┬──────────updated_at─┬─updated_at_date─┐
│  1 │ 2023-02-24 17:08:08 │      2023-02-24 │
└────┴─────────────────────┴─────────────────┘
```

<div id="ephemeral">
  ### EPHEMERAL
</div>

`EPHEMERAL [expr]`

临时列。此类型的列不会存储在表中，也无法对其执行 `SELECT`。临时列的唯一用途，是基于它们构建其他列的默认值表达式。

执行未显式指定列的插入时，会跳过此类型的列。这样做是为了保持这样一个不变性：`SELECT *` 的结果始终都可以通过 `INSERT` 再次插回表中。

示例：

```sql theme={null}
CREATE OR REPLACE TABLE test
(
    id UInt64,
    unhexed String EPHEMERAL,
    hexed FixedString(4) DEFAULT unhex(unhexed)
)
ENGINE = MergeTree
ORDER BY id;

INSERT INTO test (id, unhexed) VALUES (1, '5a90b714');

SELECT
    id,
    hexed,
    hex(hexed)
FROM test
FORMAT Vertical;

Row 1:
──────
id:         1
hexed:      Z��
hex(hexed): 5A90B714
```

<div id="alias">
  ### ALIAS
</div>

`ALIAS expr`

计算列 (同义概念) 。这种类型的列不会存储在表中，也无法向其中 `INSERT` 值。

当 `SELECT` 查询显式引用这种类型的列时，其值会在查询时根据 `expr` 计算。默认情况下，`SELECT *` 会排除 ALIAS 列。可通过设置 `asterisk_include_alias_columns` 禁用此行为。

使用 ALTER 查询添加新列时，不会为这些列补写旧数据。相反，在读取不包含这些新列值的旧数据时，默认会动态计算表达式。不过，如果计算这些表达式需要查询中未指出的其他列，则还会额外读取这些列，但仅限于需要它们的数据块。

如果向表中添加了一个新列，但之后又更改了它的默认表达式，那么旧数据使用的值也会发生变化 (即那些值未存储在磁盘上的数据) 。请注意，在执行后台合并时，如果参与合并的某个 parts 中缺少某列的数据，则会将该列的数据写入合并后的 part。

无法为嵌套数据结构中的元素设置默认值。

```sql theme={null}
CREATE OR REPLACE TABLE test
(
    id UInt64,
    size_bytes Int64,
    size String ALIAS formatReadableSize(size_bytes)
)
ENGINE = MergeTree
ORDER BY id;

INSERT INTO test VALUES (1, 4678899);

SELECT id, size_bytes, size FROM test;
┌─id─┬─size_bytes─┬─size─────┐
│  1 │    4678899 │ 4.46 MiB │
└────┴────────────┴──────────┘

SELECT * FROM test SETTINGS asterisk_include_alias_columns=1;
┌─id─┬─size_bytes─┬─size─────┐
│  1 │    4678899 │ 4.46 MiB │
└────┴────────────┴──────────┘
```

<div id="primary-key">
  ## 主键
</div>

你可以在创建表时定义[主键](/zh/reference/engines/table-engines/mergetree-family/mergetree#primary-keys-and-indexes-in-queries)。主键可以通过两种方式指定：

* 在列列表中

```sql theme={null}
CREATE TABLE [db.]table_name
(
    name1 type1, name2 type2, ...,
    PRIMARY KEY(expr1[, expr2,...])
)
ENGINE = engine;
```

* 不在列列表中

```sql theme={null}
CREATE TABLE [db.]table_name
(
    name1 type1, name2 type2, ...
)
ENGINE = engine
PRIMARY KEY(expr1[, expr2,...]);
```

<Tip>
  不能在一次查询中同时使用这两种方式。
</Tip>

<div id="constraints">
  ## 约束
</div>

除列描述外，还可以定义约束：

<div id="constraint">
  ### CONSTRAINT
</div>

```sql theme={null}
CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
(
    name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1] [compression_codec] [TTL expr1],
    ...
    CONSTRAINT constraint_name_1 CHECK boolean_expr_1,
    ...
) ENGINE = engine
```

`boolean_expr_1` 可以是任意布尔表达式。如果为该表定义了约束，那么在执行 `INSERT` 查询时，每一行都会检查所有约束。如果有任何约束不满足，server 将抛出异常，并给出约束名称和检查表达式。

添加大量约束可能会对大型 `INSERT` 查询的性能产生负面影响。

<div id="assume">
  ### ASSUME
</div>

`ASSUME` 子句用于在表上定义一个被假定为真的 `CONSTRAINT`。优化器随后可以利用该约束来提升 SQL 查询性能。

以下示例展示了在创建 `users_a` 表时如何使用 `ASSUME CONSTRAINT`：

```sql theme={null}
CREATE TABLE users_a (
    uid Int16, 
    name String, 
    age Int16, 
    name_len UInt8 MATERIALIZED length(name), 
    CONSTRAINT c1 ASSUME length(name) = name_len
) 
ENGINE=MergeTree 
ORDER BY (name_len, name);
```

这里，`ASSUME CONSTRAINT` 用于断言 `length(name)` 函数的结果始终等于 `name_len` 列的值。这意味着，每当在查询中调用 `length(name)` 时，ClickHouse 都可以将其替换为 `name_len`，这样通常会更快，因为不必调用 `length()` 函数。

随后，在执行查询 `SELECT name FROM users_a WHERE length(name) < 5;` 时，ClickHouse 可以根据 `ASSUME CONSTRAINT` 将其优化为 `SELECT name FROM users_a WHERE name_len < 5`;。这样可以让查询运行得更快，因为无需为每一行计算 `name` 的长度。

`ASSUME CONSTRAINT` **不会强制执行该约束**，它只是告知优化器该约束成立。如果该约束实际上并不成立，查询结果可能会不正确。因此，只有在你确定该约束确实成立时，才应使用 `ASSUME CONSTRAINT`。

<div id="ttl-expression">
  ## TTL 表达式
</div>

定义值的存储时长。只能为 MergeTree 家族表指定。有关详细说明，请参阅[列和表的 TTL](/zh/reference/engines/table-engines/mergetree-family/mergetree#table_engine-mergetree-ttl)。

<div id="column_compression_codec">
  ## 列压缩编解码器
</div>

默认情况下，ClickHouse 在自管理版本中使用 `lz4` 压缩，在 ClickHouse Cloud 中使用 `zstd`。

对于 `MergeTree` 引擎家族，你可以在服务器配置的 [compression](/zh/reference/settings/server-settings/settings#compression) 部分修改默认压缩方法。

你还可以在 `CREATE TABLE` 查询中为每一列单独指定压缩方法。

```sql theme={null}
CREATE TABLE codec_example
(
    dt Date CODEC(ZSTD),
    ts DateTime CODEC(LZ4HC),
    float_value Float32 CODEC(NONE),
    double_value Float64 CODEC(LZ4HC(9)),
    value Float32 CODEC(Delta, ZSTD)
)
ENGINE = <Engine>
...
```

可以指定 `Default` 编解码器，以引用默认压缩；它在运行时可能会取决于不同的设置 (以及数据属性) 。
示例：`value UInt64 CODEC(Default)` — 等同于未指定编解码器。

你还可以从列中移除当前的 CODEC，并使用 config.xml 中的默认压缩：

```sql theme={null}
ALTER TABLE codec_example MODIFY COLUMN float_value CODEC(Default);
```

编解码器可以串联使用，例如 `CODEC(Delta, Default)`。

<Tip>
  不能使用 `lz4` 等外部工具解压 ClickHouse 数据库文件。请改用专用的 [clickhouse-compressor](https://github.com/ClickHouse/ClickHouse/tree/master/programs/compressor) 工具。
</Tip>

以下表引擎支持压缩：

* [MergeTree](/zh/reference/engines/table-engines/mergetree-family/mergetree) 家族。支持列压缩编解码器，并可通过 [compression](/zh/reference/settings/server-settings/settings#compression) 设置选择默认压缩方法。
* [Log](/zh/reference/engines/table-engines/log-family) 家族。默认使用 `lz4` 压缩方法，并支持列压缩编解码器。
* [Set](/zh/reference/engines/table-engines/special/set)。仅支持默认压缩。
* [Join](/zh/reference/engines/table-engines/special/join)。仅支持默认压缩。

ClickHouse 支持通用编解码器和专用编解码器。

<div id="general-purpose-codecs">
  ### 通用编解码器
</div>

<div id="none">
  #### NONE
</div>

`NONE` — 不压缩。

<div id="lz4">
  #### LZ4
</div>

`LZ4` — 默认使用的无损[数据压缩算法](https://github.com/lz4/lz4)。采用 LZ4 快速压缩。

<div id="lz4hc">
  #### LZ4HC
</div>

`LZ4HC[(level)]` — LZ4 HC (高压缩) 算法，支持配置级别。默认级别：9。设置 `level <= 0` 时，将使用默认级别。可选级别：\[1, 12]。建议级别范围：\[4, 9]。

<div id="zstd">
  #### ZSTD
</div>

`ZSTD[(level)]` — 使用可配置 `level` 的 [ZSTD 压缩算法](https://en.wikipedia.org/wiki/Zstandard)。可选级别：\[1, 22]。默认级别：1。

较高的压缩级别适用于非对称场景，例如只压缩一次、反复解压。级别越高，压缩效果越好，但 CPU 使用率也越高。

<div id="zstd_qat">
  #### 已废弃：ZSTD\_QAT
</div>

<div id="deflate_qpl">
  #### 已废弃：DEFLATE\_QPL
</div>

<div id="specialized-codecs">
  ### 专用编解码器
</div>

这些编解码器旨在利用数据的特定特性，进一步提升压缩效果。其中有些编解码器本身并不直接压缩数据，而是先对数据进行预处理，以便在第二阶段使用通用编解码器时获得更高的压缩率。

<div id="delta">
  #### Delta
</div>

`Delta(delta_bytes)` — 一种压缩方法，其中原始值会替换为相邻两个值之差，但第一个值保持不变。`delta_bytes` 是原始值的最大大小，默认值为 `sizeof(type)`。将 `delta_bytes` 作为参数指定的做法已弃用，相关支持将在未来版本中移除。Delta 是一种数据预处理编解码器，也就是说，不能单独使用。

<div id="doubledelta">
  #### DoubleDelta
</div>

`DoubleDelta(bytes_size)` — 计算二阶增量，并以紧凑的二进制形式写入。`bytes_size` 的含义与 [Delta](#delta) 编解码器中的 `delta_bytes` 类似。将 `bytes_size` 指定为参数的做法已弃用，未来版本将移除对此用法的支持。对于步长固定的单调序列 (例如时间序列数据) ，可获得最佳压缩率。可用于任何数值类型。它实现了 Gorilla TSDB 中使用的算法，并将其扩展为支持 64 位类型。对于 32 位增量，会额外使用 1 个比特：使用 5 位前缀而不是 4 位前缀。更多信息请参见 [Gorilla: A Fast, Scalable, In-Memory Time Series Database](http://www.vldb.org/pvldb/vol8/p1816-teller.pdf) 中的 Compressing Time Stamps。DoubleDelta 是一种用于数据准备的编解码器，即不能单独使用。

<div id="gcd">
  #### GCD
</div>

`GCD()` - - 计算列中各个值的最大公约数 (GCD) ，然后将每个值除以该 GCD。可用于整数、小数和日期/时间列。该编解码器非常适合用于值按 GCD 的倍数变化 (增大或减小) 的列，例如 24、28、16、24、8、24 (GCD = 4) 。GCD 是一种数据预处理编解码器，也就是说，不能单独使用。

<div id="gorilla">
  #### Gorilla
</div>

`Gorilla(bytes_size)` — 计算当前浮点值与前一个浮点值之间的 XOR，并将结果以紧凑的二进制形式写入。连续值之间的差异越小，也就是说序列中的值变化越慢，压缩率就越高。它实现了 Gorilla TSDB 使用的算法，并将其扩展为支持 64 位类型。`bytes_size` 的可选值为 1、2、4、8；如果 `sizeof(type)` 等于 1、2、4 或 8，则默认值为 `sizeof(type)`。在其他所有情况下，默认值为 1。更多信息请参见 [Gorilla: A Fast, Scalable, In-Memory Time Series Database](https://doi.org/10.14778/2824032.2824078) 的第 4.1 节。

<div id="alp">
  #### ALP
</div>

`ALP()` — 一种基于十进制标度的浮点数据自适应无损压缩方法。ALP 会尝试将每个值用十进制幂表示为精确的缩放整数，然后使用 Frame-of-Reference 和位打包压缩得到的整数。无法被精确表示的值会作为原始例外值存储。它最适用于源自十进制的数值 (例如测量值、货币金额) 。支持 `Float32` 和 `Float64`。详情参见 [ALP: Adaptive lossless floating-point compression](https://ir.cwi.nl/pub/33334)。

<Note>
  此编解码器处于 Experimental 阶段，使用前需要设置 `SET allow_experimental_codecs = 1`。
</Note>

<div id="fpc">
  #### FPC
</div>

`FPC(level, float_size)` - 使用两种预测器中效果更好的一种，反复预测序列中的下一个浮点值，然后将实际值与预测值进行 XOR，并对结果执行前导零压缩。与 Gorilla 类似，在存储一系列变化缓慢的浮点值时，这种方式效率很高。对于 64 位值 (double) ，FPC 比 Gorilla 更快；对于 32 位值，则要视具体情况而定。可选的 `level` 值为：1-28，默认值为 12。可选的 `float_size` 值为：4、8；如果类型为 Float，则默认值为 `sizeof(type)`。其他所有情况下，默认值均为 4。有关该算法的详细说明，请参阅 [High Throughput Compression of Double-Precision Floating-Point Data](https://userweb.cs.txstate.edu/~burtscher/papers/dcc07a.pdf)。

<div id="t64">
  #### T64
</div>

`T64` —— 一种压缩方法，用于裁剪整数数据类型 (包括 `Enum`、`Date` 和 `DateTime`) 中未使用的高位。在该算法的每一步中，codec 都会取一个包含 64 个值的块，将其放入一个 64x64 位矩阵中，对矩阵进行转置，裁剪值中未使用的位，并将其余部分作为一个序列返回。所谓未使用的位，是指在使用该压缩的数据分区片段中，整体最大值与最小值之间没有差异的那些位。

`DoubleDelta` 和 `Gorilla` codec 在 Gorilla TSDB 中用作其压缩算法的组成部分。Gorilla 方法在存在一组变化缓慢的值及其时间戳的场景下效果显著。时间戳可通过 `DoubleDelta` codec 进行高效压缩，而值可通过 `Gorilla` codec 进行高效压缩。例如，要获得存储效率更高的表，可以按如下配置创建：

```sql theme={null}
CREATE TABLE codec_example
(
    timestamp DateTime CODEC(DoubleDelta),
    slow_values Float32 CODEC(Gorilla)
)
ENGINE = MergeTree()
```

<div id="encryption-codecs">
  ### 加密编解码器
</div>

这些编解码器实际上并不压缩数据，而是对磁盘上的数据进行加密。只有在通过[encryption](/zh/reference/settings/server-settings/settings#encryption)设置指定加密密钥时，这些编解码器才可用。请注意，加密只有放在编解码器管道的末端才有意义，因为加密后的数据通常无法再以任何有意义的方式进行压缩。

加密编解码器：

<div id="aes_128_gcm_siv">
  #### AES\_128\_GCM\_SIV
</div>

`CODEC('AES-128-GCM-SIV')` — 使用 [RFC 8452](https://tools.ietf.org/html/rfc8452) 中定义的 GCM-SIV 模式，通过 AES-128 对数据进行加密。

<div id="aes-256-gcm-siv">
  #### AES-256-GCM-SIV
</div>

`CODEC('AES-256-GCM-SIV')` — 使用 GCM-SIV 模式的 AES-256 加密数据。

这些编解码器使用固定的 nonce，因此加密是确定性的。这使其与支持去重的引擎 (例如 [ReplicatedMergeTree](/zh/reference/engines/table-engines/mergetree-family/replication)) 兼容，但也存在一个弱点：当同一个数据块被加密两次时，生成的密文会完全相同，因此能够读取磁盘的攻击者可以看出二者是相同的 (尽管只能看出这一点，无法获取其内容) 。

<Note>
  大多数引擎 (包括 "\*MergeTree" 家族) 都会在磁盘上创建索引文件，而不会应用编解码器。这意味着如果加密列被建立索引，明文就会出现在磁盘上。
</Note>

<Note>
  如果你执行的 SELECT 查询中指定了加密列中的某个特定值 (例如在 WHERE 子句中) ，该值可能会出现在 [system.query\_log](/zh/reference/system-tables/query_log) 中。你可能需要禁用日志记录。
</Note>

**示例**

```sql theme={null}
CREATE TABLE mytable
(
    x String CODEC(AES_128_GCM_SIV)
)
ENGINE = MergeTree ORDER BY x;
```

<Note>
  如果需要启用压缩，必须显式指定。否则，数据只会加密，不会压缩。
</Note>

**示例**

```sql theme={null}
CREATE TABLE mytable
(
    x String CODEC(Delta, LZ4, AES_128_GCM_SIV)
)
ENGINE = MergeTree ORDER BY x;
```

<div id="temporary-tables">
  ## 临时表
</div>

<Note>
  请注意，临时表不会被复制。因此，无法保证插入临时表的数据在其他副本上也可用。临时表的主要用途是在单个会话期间查询或连接较小的外部数据集。
</Note>

ClickHouse 支持临时表，具有以下特性：

* 临时表会在会话结束时消失，包括连接中断时。
* 如果未指定引擎，临时表会使用 Memory 表引擎；此外，它还可以使用除 Replicated 和 `KeeperMap` 引擎之外的任何表引擎。
* 临时表不能指定 DB。它是在数据库之外创建的。
* 无法使用分布式 DDL 查询通过 `ON CLUSTER` 在集群中的所有服务器上创建临时表：该表仅存在于当前会话中。
* 如果临时表与其他表同名，且查询在未指定 DB 的情况下使用该表名，则会使用临时表。
* 对于分布式查询处理，查询中使用的采用 Memory 引擎的临时表会被传递到远程服务器。

要创建临时表，请使用以下语法：

```sql theme={null}
CREATE [OR REPLACE] TEMPORARY TABLE [IF NOT EXISTS] table_name
(
    name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],
    name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],
    ...
) [ENGINE = engine]
```

在大多数情况下，临时表并不是手动创建的，而是在查询中使用外部数据，或使用分布式 `(GLOBAL) IN` 时创建。更多信息请参见相应章节

也可以使用 [ENGINE = Memory](/zh/reference/engines/table-engines/special/memory) 的表来替代临时表。

<div id="replace-table">
  ## REPLACE TABLE
</div>

`REPLACE` 语句允许你以[原子方式](/zh/concepts/core-concepts/glossary#atomicity)更新表。

<Note>
  该语句支持 [`Atomic`](/zh/reference/engines/database-engines/atomic) 和 [`Replicated`](/zh/reference/engines/database-engines/replicated) 数据库引擎，
  它们分别是 ClickHouse 和 ClickHouse Cloud 的默认数据库引擎。
</Note>

通常，如果你需要从表中删除部分数据，
可以创建一个新表，并用不会检索到不需要数据的 `SELECT` 语句填充该表，
然后删除旧表，再将新表重命名。
下面的示例演示了这种方法：

```sql theme={null}
CREATE TABLE myNewTable AS myOldTable;

INSERT INTO myNewTable
SELECT * FROM myOldTable 
WHERE CounterID <12345;

DROP TABLE myOldTable;

RENAME TABLE myNewTable TO myOldTable;
```

除了上述方法，也可以使用 `REPLACE` (前提是使用默认数据库引擎) 来达到相同效果：

```sql theme={null}
REPLACE TABLE myOldTable
ENGINE = MergeTree()
ORDER BY CounterID 
AS
SELECT * FROM myOldTable
WHERE CounterID <12345;
```

<div id="syntax">
  ### 语法
</div>

```sql theme={null}
{CREATE [OR REPLACE] | REPLACE} TABLE [db.]table_name
```

<Note>
  `CREATE` 语句的所有语法形式同样适用于该语句。对不存在的表执行 `REPLACE` 会报错。
</Note>

<div id="examples">
  ### 示例：
</div>

<Tabs>
  <Tab title="本地">
    请看下表：

    ```sql theme={null}
    CREATE DATABASE base 
    ENGINE = Atomic;

    CREATE OR REPLACE TABLE base.t1
    (
        n UInt64,
        s String
    )
    ENGINE = MergeTree
    ORDER BY n;

    INSERT INTO base.t1 VALUES (1, 'test');

    SELECT * FROM base.t1;

    ┌─n─┬─s────┐
    │ 1 │ test │
    └───┴──────┘
    ```

    我们可以使用 `REPLACE` 语句清空所有数据：

    ```sql theme={null}
    CREATE OR REPLACE TABLE base.t1 
    (
        n UInt64,
        s Nullable(String)
    )
    ENGINE = MergeTree
    ORDER BY n;

    INSERT INTO base.t1 VALUES (2, null);

    SELECT * FROM base.t1;

    ┌─n─┬─s──┐
    │ 2 │ \N │
    └───┴────┘
    ```

    或者，也可以使用 `REPLACE` 语句修改表结构：

    ```sql theme={null}
    REPLACE TABLE base.t1 (n UInt64) 
    ENGINE = MergeTree 
    ORDER BY n;

    INSERT INTO base.t1 VALUES (3);

    SELECT * FROM base.t1;

    ┌─n─┐
    │ 3 │
    └───┘
    ```
  </Tab>

  <Tab title="Cloud">
    请看 ClickHouse Cloud 上的下表：

    ```sql theme={null}
    CREATE DATABASE base;

    CREATE OR REPLACE TABLE base.t1 
    (
        n UInt64,
        s String
    )
    ENGINE = MergeTree
    ORDER BY n;

    INSERT INTO base.t1 VALUES (1, 'test');

    SELECT * FROM base.t1;

    1    test
    ```

    我们可以使用 `REPLACE` 语句清空所有数据：

    ```sql theme={null}
    CREATE OR REPLACE TABLE base.t1 
    (
        n UInt64, 
        s Nullable(String)
    )
    ENGINE = MergeTree
    ORDER BY n;

    INSERT INTO base.t1 VALUES (2, null);

    SELECT * FROM base.t1;

    2    
    ```

    或者，也可以使用 `REPLACE` 语句修改表结构：

    ```sql theme={null}
    REPLACE TABLE base.t1 (n UInt64) 
    ENGINE = MergeTree 
    ORDER BY n;

    INSERT INTO base.t1 VALUES (3);

    SELECT * FROM base.t1;

    3
    ```
  </Tab>
</Tabs>

<div id="comment-clause">
  ## COMMENT 子句
</div>

您可以在创建表时添加注释。

**语法**

```sql theme={null}
CREATE TABLE [db.]table_name
(
    name1 type1, name2 type2, ...
)
ENGINE = engine
COMMENT 'Comment'
```

<Note>
  `COMMENT` 子句必须在 `PARTITION BY`、`ORDER BY` 以及存储专用 `SETTINGS` 等所有存储相关子句**之后**指定。

  在 `COMMENT` 子句之后，只会解析查询专用 `SETTINGS` (如 `max_threads` 等) ，不会解析存储相关设置。

  这意味着，正确的子句顺序是：

  * `ENGINE`
  * 存储子句
  * `COMMENT`
  * 查询设置 (如有)
</Note>

**示例**

```sql title="Query" theme={null}
CREATE TABLE t1 (x String) ENGINE = Memory COMMENT 'The temporary table';
SELECT name, comment FROM system.tables WHERE name = 't1';
```

```text title="Response" theme={null}
┌─name─┬─comment─────────────┐
│ t1   │ The temporary table │
└──────┴─────────────────────┘
```

<div id="related-content">
  ## 相关内容
</div>

* 博客：[使用 schema 和编解码器优化 ClickHouse](https://clickhouse.com/blog/optimize-clickhouse-codecs-compression-schema)
* 博客：[在 ClickHouse 中处理时间序列数据](https://clickhouse.com/blog/working-with-time-series-data-and-functions-ClickHouse)
