跳转到主要内容
向表中插入数据。 语法
你可以使用 (c1, c2, c3) 指定要插入的列列表。你也可以使用带有列匹配器 (如 *) 和/或修饰符 (如 APPLYEXCEPTREPLACE) 的表达式。 例如,假设有如下表:
如果你想将数据插入除列 b 之外的所有列,可以使用 EXCEPT 关键字。结合上面的语法,你需要确保插入的值数量 (VALUES (v11, v13)) 与指定的列数 ((c1, c3)) 一致:
在此示例中,我们可以看到,第二个插入的行中,ac 列使用传入的值填充,b 列则使用默认值填充。也可以使用 DEFAULT 关键字来插入默认值:
如果列列表未包含所有现有列,其余列将使用以下内容填充:
  • 根据表定义中指定的 DEFAULT 表达式计算得出的值。
  • 如果未定义 DEFAULT 表达式,则填充为零和空字符串。
数据可以通过 ClickHouse 支持的任意一种 格式 传递给 INSERT。必须在查询中显式指定格式:
例如,以下查询格式与基础形式的 INSERT ... VALUES 完全相同:
ClickHouse 会移除数据前的所有空格,以及一个换行符 (如果存在) 。构造查询时,建议将数据放在查询运算符后的新一行中;如果数据以空格开头,这一点尤其重要。 示例:
你可以使用命令行客户端HTTP 接口,将数据与查询分开插入。
如果你想为 INSERT 查询指定 SETTINGS,则必须在 FORMAT 子句之前指定,因为 FORMAT format_name 之后的所有内容都会被视为数据。例如:

约束

如果表定义了约束,系统会检查插入数据中每一行是否满足相应的表达式。如果其中任何一项约束不满足,服务器将引发异常,其中包含约束名称和表达式,并停止该查询。

数据类型验证

ClickHouse 仅在创建表 (CREATE TABLE) 和修改 schema (ALTER TABLE) 时验证允许使用的数据类型 (由 enable_time_time64_typeallow_suspicious_low_cardinality_typesallow_suspicious_fixed_string_types 等设置控制) ,不会在 INSERT 时进行验证。 这意味着,如果某个包含不允许数据类型的表已经存在,那么即使 server 上禁用了相应设置,仍然可以向其中插入数据。这是有意为之——表一旦创建完成,insert 操作就不应被控制类型创建的设置所阻止。 例如:
因此,较新版本的客户端 (其中某项设置默认启用) 可以向较旧版本的服务器 (其中该设置已禁用) 插入包含不允许的数据类型的数据,前提是目标表已具有相应的列类型。校验是在 DDL 层面强制执行的,而不是在 DML 层面。

插入 SELECT 结果

语法
列会根据它们在 SELECT 子句中的位置进行映射。不过,它们在 SELECT 表达式中的名称与 INSERT 目标表中的名称可以不同。如有必要,会执行类型转换。 除 Values 格式外,其他任何数据格式都不允许将值设置为 now()1 + 2 等表达式。Values 格式允许在有限范围内使用表达式,但不建议这样做,因为在这种情况下会使用低效的代码来执行这些表达式。 不支持其他修改数据分区片段的查询:UPDATEDELETEREPLACEMERGEUPSERTINSERT UPDATE。 不过,你可以使用 ALTER TABLE ... DROP PARTITION 删除旧数据。 如果 SELECT 子句包含表函数 input(),则必须在查询末尾指定 FORMAT 子句。 若要向非 Nullable 数据类型的列中插入默认值而不是 NULL,请启用 insert_null_as_default 设置。 INSERT 也支持 CTE (公共表表达式) 。例如,以下两条语句是等价的:

从文件中插入数据

语法
使用上述语法可从存储在客户端侧的一个或多个文件中插入数据。file_nametype 是字符串字面量。输入文件的格式必须在 FORMAT 子句中设置。 支持压缩文件。压缩类型会根据文件名扩展名自动识别,也可以在 COMPRESSION 子句中显式指定。支持的类型包括:'none''gzip''deflate''br''xz''zstd''lz4''bz2' 此功能可用于命令行客户端clickhouse-local 示例

使用 FROM INFILE 从单个文件导入数据

使用命令行客户端执行以下查询:
Query
Response

使用通配符通过 FROM INFILE 处理多个文件

此示例与前一个示例非常相似,但插入操作会通过 FROM INFILE 'input_*.csv' 从多个文件执行。
除了使用 * 选择多个文件外,你还可以使用范围 ({1,2}{1..9}) 以及其他通配符替换规则。以下三种写法都适用于上面的示例:

使用表函数进行插入

可以向由表函数引用的表中插入数据。 语法
示例 以下查询使用了 remote 表函数:
Query
Response

向 ClickHouse Cloud 插入数据

默认情况下,ClickHouse Cloud 中的服务会提供多个副本,以实现高可用性。当你连接到某个服务时,系统会与其中一个副本建立连接。 INSERT 成功后,数据会写入底层存储。不过,副本接收到这些更新可能需要一些时间。因此,如果你使用另一个连接,在其他副本上执行 SELECT 查询,更新后的数据可能还无法立即反映出来。 可以使用 select_sequential_consistency 强制副本接收最新更新。以下是一个使用此设置的 SELECT 查询示例:
请注意,使用 select_sequential_consistency 会增加 ClickHouse Keeper (ClickHouse Cloud 在内部使用的协调服务) 的负载,并且可能会因该服务的负载情况而导致性能下降。除非确有必要,我们不建议启用此设置。推荐的做法是在同一 session 中执行读写操作,或使用采用 native protocol 的客户端驱动 (因此支持粘性连接) 。

在复制环境中插入数据

在复制环境中,数据完成复制后,才会在其他副本上可见。执行 INSERT 后,数据会立即开始复制 (即下载到其他副本) 。这与 ClickHouse Cloud 不同:在 ClickHouse Cloud 中,数据会立即写入共享存储,副本则通过订阅元数据变更进行同步。 请注意,在复制环境中,INSERTs 有时可能耗时较长 (大约为 1 秒) ,因为这需要提交到 ClickHouse Keeper 以达成分布式共识。使用 S3 作为存储也会带来额外延迟。

性能注意事项

INSERT 会按主键对输入数据排序,并按分区键将其拆分到不同分区中。如果一次将数据插入多个分区,INSERT 查询的性能可能会明显下降。为避免这种情况:
  • 以较大的批次写入数据,例如每次 100,000 行。
  • 在将数据上传到 ClickHouse 之前,先按分区键对数据分组。
在以下情况下,性能通常不会下降:
  • 实时写入数据。
  • 上传通常按时间排序的数据。

异步插入

对于小而频繁的插入操作,可以采用异步插入的方式。此类插入的数据会先合并为批次,然后再安全地写入表中。要使用异步插入,请启用 async_insert 设置。 使用 async_insertBuffer 表引擎 都会带来额外的缓冲。

大规模或耗时较长的插入

当插入大量数据时,ClickHouse 会通过称为“squashing”的过程来优化写入性能。内存中较小的已插入数据块会先合并并压缩成更大的块,然后再写入磁盘。squashing 可减少每次写入操作的相关开销。在此过程中,ClickHouse 每完成写入 max_insert_block_size 行后,这部分已插入的数据就可以被查询到。 另请参见
最后修改于 2026年6月25日