导入数据
将数据插入表中。句法:
INSERT INTO [TABLE] [db.]table [(c1, c2, c3)] [SETTINGS ...] VALUES (v11, v12, v13), (v21, v22, v23), ...
您可以使用 指定要插入的列的列表。您还可以使用带有列匹配器的(c1, c2, c3)
表达式,例如和/或修饰符,例如APPLY、EXCEPT、REPLACE。*
例如,考虑下表:
SHOW CREATE insert_select_testtable;
CREATE TABLE insert_select_testtable
(
`a` Int8,
`b` String,
`c` Int8
)
ENGINE = MergeTree()
ORDER BY a
INSERT INTO insert_select_testtable (*) VALUES (1, 'a', 1) ;
如果要在除“b”之外的所有列中插入数据,则需要在括号中传递您选择的列数(即多少个值):
INSERT INTO insert_select_testtable (* EXCEPT(b)) Values (2, 2);
SELECT * FROM insert_select_testtable;
┌─a─┬─b─┬─c─┐
│ 2 │ │ 2 │
└───┴───┴───┘
┌─a─┬─b─┬─c─┐
│ 1 │ a │ 1 │
└───┴───┴───┘
在这个例子中,可以看到插入的第二行有a
和c
列由传递的值填充,并且b
默认填充了值。也可以使用DEFAULT
关键字插入默认值:
INSERT INTO insert_select_testtable VALUES (1, DEFAULT, 1) ;
如果列表未包括所有现有列,则其余列将填充:
DEFAULT
根据表定义中指定的表达式计算的值。DEFAULT
如果未定义表达式,则为零和空字符串。
数据可以以ClickHouse支持的任何格式传递给INSERT 。格式必须在查询中明确指定:
INSERT INTO [db.]table [(c1, c2, c3)] FORMAT format_name data_set
例如,以下查询格式与 INSERT ... VALUES 的基本版本相同:
INSERT INTO [db.]table [(c1, c2, c3)] FORMAT Values (v11, v12, v13), (v21, v22, v23), ...
ClickHouse 会删除数据前的所有空格和一个换行符(如果有)。在形成查询时,我们建议将数据放在查询运算符后的新行上(如果数据以空格开头,这一点很重要)。例如:
INSERT INTO t FORMAT TabSeparated
11 Hello, world!
22 Qwerty
您可以使用命令行客户端或HTTP 接口从查询中单独插入数据。
笔记
如果要指定SETTINGS
查询INSERT
,则必须在子句之前 执行此操作,因为之后的所有内容都被视为数据。例如:FORMAT``FORMAT format_name
约束条件
如果表有约束条件,则将对插入的每一行数据检查其表达式。如果任何约束不满足 — 服务器将引发包含约束名称和表达式的异常,查询将停止。
插入SELECT的结果
句法:
INSERT INTO [TABLE] [db.]table [(c1, c2, c3)] SELECT ...
列根据其在SELECT子句中的位置进行映射。但是,它们在SELECT表达式和INSERT的表中的名称可能不同。如有必要,将执行类型转换。
除了Values之外,其他数据格式都不允许将值设置为诸如等表达式now()
。Values1 + 2
格式允许有限地使用表达式,但不建议这样做,因为在这种情况下,执行表达式的代码效率低下。
不支持修改数据部分的其他查询:UPDATE
,DELETE
,REPLACE
,MERGE
,UPSERT
。INSERT UPDATE
但是,您可以使用 删除旧数据ALTER TABLE ... DROP PARTITION
。
FORMAT``SELECT
如果子句包含表函数input() ,则必须在查询末尾指定子句。
要插入默认值而不是NULL
插入不可空数据类型的列,请启用insert_null_as_default设置。
INSERT
还支持CTE(common table expression)。例如,下面两个语句是等效的:
INSERT INTO x WITH y AS (SELECT * FROM numbers(10)) SELECT * FROM y;
WITH y AS (SELECT * FROM numbers(10)) INSERT INTO x SELECT * FROM y;
从文件插入数据
句法:
INSERT INTO [TABLE] [db.]table [(c1, c2, c3)] FROM INFILE file_name [COMPRESSION type] [SETTINGS ...] [FORMAT format_name]
使用上述语法从存储在客户端的一个或多个文件中插入数据。file_name
和type
是字符串文字。必须在子句中设置输入文件格式FORMAT
。
支持压缩文件。压缩类型通过文件名的扩展名检测。或者可以在子句中明确指定。支持COMPRESSION的类型有:'none'``'gzip'``'deflate'``'br'``'xz'``'zstd'``'lz4'``'bz2'
此功能在命令行客户端和clickhouse-local中可用。
带有 FROM INFILE 的单个文件
使用命令行客户端执行以下查询:
echo 1,A > input.csv ; echo 2,B >> input.csv
clickhouse-client --query="CREATE TABLE table_from_file (id UInt32, text String) ENGINE=MergeTree() ORDER BY id;"
clickhouse-client --query="INSERT INTO table_from_file FROM INFILE 'input.csv' FORMAT CSV;"
clickhouse-client --query="SELECT * FROM table_from_file FORMAT PrettyCompact;"
结果:
┌─id─┬─text─┐
│ 1 │ A │
│ 2 │ B │
└────┴──────┘
使用globs包含FROM INFILE的多个文件
此示例与前一个示例非常相似,但使用从多个文件插入FROM INFILE 'input_*.csv
。
echo 1,A > input_1.csv ; echo 2,B > input_2.csv
clickhouse-client --query="CREATE TABLE infile_globs (id UInt32, text String) ENGINE=MergeTree() ORDER BY id;"
clickhouse-client --query="INSERT INTO infile_globs FROM INFILE 'input_*.csv' FORMAT CSV;"
clickhouse-client --query="SELECT * FROM infile_globs FORMAT PrettyCompact;"
使用表函数插入
可以将数据插入到表函数引用的表中。
句法:
INSERT INTO [TABLE] FUNCTION table_func ...
例子
远程表函数用于以下查询:
CREATE TABLE simple_table (id UInt32, text String) ENGINE=MergeTree() ORDER BY id;
INSERT INTO TABLE FUNCTION remote('localhost', default.simple_table)
VALUES (100, 'inserted via remote()');
SELECT * FROM simple_table;
结果:
┌──id─┬─text──────────────────┐
│ 100 │ inserted via remote() │
└─────┴───────────────────────┘
性能注意事项
INSERT
按主键对输入数据进行排序,并按分区键将它们拆分为多个分区。如果一次将数据插入多个分区,则会显著降低查询的性能INSERT
。要避免这种情况:
- 以相当大的批量添加数据,例如一次添加 100,000 行。
- 在将数据上传到 ClickHouse 之前,按分区键对数据进行分组。
如果出现以下情况,性能不会下降:
- 数据是实时添加的。
- 您上传的数据通常按时间排序。
非同步插入数据
可以异步插入少量但频繁的数据。此类插入的数据将组合成批数据,然后安全地插入到表中。要使用异步插入,请启用此async_insert
设置。
使用async_insert
或Buffer表引擎会导致额外的缓冲。
大型或长时间运行的插入数据
当您插入大量数据时,ClickHouse将通过称为“压缩”的过程来优化写入性能。内存中插入的小块数据在写入磁盘之前会合并并压缩为更大的块。压缩可减少与每次写入操作相关的开销。在此过程中,ClickHouse完成每行写入后即可查询插入的数据max_insert_block_size
。