跳到主要内容
版本:1.2

CREATE

CREATE 用于创建新的数据库或者表。

CREATE DATABASE

Syntax

创建新数据库:

CREATE DATABASE [IF NOT EXISTS] db_name [WITH <options>]

如果 db_name 数据库已经存在,CREATE 语句的行为如下:

  • 不会创建新的数据库。
  • IF NOT EXISTS 子句被指定时,不会返回错误。
  • 否则,返回错误。

数据库也可以通过使用 WITH 关键字配置与 CREATE TABLE 语句类似的选项。数据库支持以下选项:

  • ttl - 数据库中所有表的数据存活时间(不能设置为 instant
  • memtable.type - 内存表类型(time_seriespartition_tree
  • append_mode - 数据库中的表是否为仅追加模式(true/false
  • merge_mode - 合并重复行的策略(last_rowlast_non_null
  • skip_wal - 是否为数据库中的表禁用预写日志('true'/'false'
  • sst_format - 数据库中表的 SST(Sorted String Table)文件格式(flatprimary_key
  • compaction.* - 压缩相关设置(如 compaction.typecompaction.twcs.time_window

阅读更多关于表选项的信息。

重要的行为差异

数据库选项的行为有所不同:

  • TTL 和 Compaction 选项ttlcompaction.*):这些选项具有持续影响。没有指定这些值的表会持续继承数据库级别的值。更改数据库 TTL 或 compaction 选项会立即影响所有没有明确自行设置这些选项的表。

  • 其他选项memtable.typeappend_modemerge_modeskip_walsst_format):这些选项充当模板变量,仅在创建新表时应用。更改这些数据库级别的选项不会影响已存在的表——它们仅作为新创建表的默认值。

在创建表时,如果未提供相应的表选项,将使用在数据库级别配置的选项或者默认值。

示例

创建名为 test 的数据库:

CREATE DATABASE test;
Query OK, 1 row affected (0.05 sec)

使用 IF NOT EXISTS 再次创建:

CREATE DATABASE IF NOT EXISTS test;

创建一个具有 7 天 TTL(数据存活时间)的数据库,也就是该数据库中的所有表如果没有单独设置 TTL 选项,都将继承此选项值。

CREATE DATABASE test WITH (ttl='7d');

创建一个带有多个选项的数据库,包括仅追加模式和自定义内存表类型:

CREATE DATABASE test WITH (
ttl='30d',
'memtable.type'='partition_tree',
'append_mode'='true'
);

创建一个禁用预写日志并设置自定义合并模式的数据库:

CREATE DATABASE test WITH (
'skip_wal'='true',
'merge_mode'='last_non_null'
);

创建一个指定 SST 文件格式的数据库:

CREATE DATABASE test WITH ('sst_format'='flat');

CREATE TABLE

Syntax

db 或当前数据库中创建新表:

CREATE TABLE [IF NOT EXISTS] [db.]table_name
(
column1 type1 [NULL | NOT NULL] [DEFAULT expr1] [TIME INDEX] [PRIMARY KEY] [indexes] [COMMENT comment1],
column2 type2 [NULL | NOT NULL] [DEFAULT expr2] [TIME INDEX] [PRIMARY KEY] [indexes] [COMMENT comment2],
...
[TIME INDEX (column)],
[PRIMARY KEY(column1, column2, ...)],
)
[
PARTITION ON COLUMNS(column1, column2, ...) (
<PARTITION EXPR>,
...
)
]
ENGINE = engine WITH([TTL | storage | ...] = expr, ...)

表 schema 由 ENGINE 之前的括号指定,表 schema 是列的定义和表的约束。 列定义包括列名称和数据类型,以及可选的 NULLNOT NULLDEFAULT 等。

关于 engine 选项和表引擎的选择,请阅读表引擎介绍。

表约束

表约束包括以下内容:

  • TIME INDEX 指定时间索引列,每个表只能有一个时间索引列。它表示 GreptimeDB 的 数据模型 中的 Timestamp 类型。
  • PRIMARY KEY 指定表的主键列,它表示 GreptimeDB 的 数据模型 中的 Tag 类型。它不能包含时间索引列,但是它总是隐式地将时间索引列添加到键的末尾。
  • 其他列是 GreptimeDB 的 数据模型 中的 Field 类型。
注意

PRIMARY KEY 列和 TIME INDEX 共同组成用于排序与合并数据行的存储键。与关系数据库的主键不同,该存储键不强制唯一性。merge_modeappend_mode决定 GreptimeDB 如何处理存储键相同的数据行。

如果表已经存在且创建表时指定了 IF NOT EXISTSCREATE 语句不会返回错误;否则返回错误。

索引

GreptimeDB 提供了丰富的索引实现来加速查询,请在索引章节查看更多信息。

表选项

用户可以使用 WITH 添加表选项。有效的选项包括以下内容:

选项描述
ttl表数据的存储时间一个时间范围字符串,例如 '60m', '1h' 代表 1 小时, '14d' 代表 14 天等。支持的时间单位有:s / m / h / d
storage自定义表的存储引擎,存储引擎提供商的名字字符串,类似 S3Gcs 等。必须在 [[storage.providers]] 列表里配置,参考 configuration
compaction.typeCompaction 策略字符串值。只支持 twcs。你可以阅读这篇文章来了解 twcs compaction 策略
compaction.twcs.trigger_file_num某个窗口内触发 compaction 的最小文件数量阈值字符串值,如 '8'。只在 compaction.typetwcs 时可用
compaction.twcs.time_windowCompaction 时间窗口字符串值,如 '1d' 表示 1 天。该表会根据时间戳将数据分区到不同的时间窗口中。只在 compaction.typetwcs 时可用
compaction.twcs.max_output_file_sizeTWCS compaction 的最大输出文件大小字符串值,如 '1GB'、'512MB'。设置 TWCS compaction 产生的文件的最大大小。只在 compaction.typetwcs 时可用
memtable.typememtable 的类型字符串值,支持 time_seriespartition_tree
append_mode该表是否时 append-only 的字符串值。默认值为 'false',根据 'merge_mode' 按主键和时间戳删除重复行。设置为 'true' 可以开启 append 模式和创建 append-only 表,保留所有重复的行
merge_mode合并重复行的策略字符串值。只有当 append_mode 为 'false' 时可用。默认值为 last_row,保留相同主键和时间戳的最后一行。设置为 last_non_null 则保留相同主键和时间戳的最后一个非空字段。
sst_formatSST 文件的格式字符串值,支持 primary_keyflat。默认为 flatflat 格式建议用于具有高基数主键的表。
comment表级注释字符串值。
index.typeIndex 类型仅用于 metric engine 字符串值,支持 none, skipping.
skip_wal是否关闭表的预写日志字符串类型。当设置为 'true' 时表的写入数据将不会持久化到预写日志,可以避免存储磨损同时提升写入吞吐。但是当进程重启时,尚未 flush 的数据会丢失。请仅在数据源本身可以确保可靠性的情况下使用此功能。
write_buffer_size该表的单 region 写缓冲区阻塞阈值字符串类型,例如 '512MB''1GB'。设置为正值后,mutable memtable 内存用量达到该值的一半时,GreptimeDB 会调度 flush;达到该值时会阻塞写入,达到该值的 2 倍时会拒绝写入。该表选项会覆盖 region_engine.mito.default_region_write_buffer_size。即使引擎默认值非零,显式设置为 '0' 也会禁用单 region 限制。取消设置会移除表级覆盖,并回退到引擎默认值。
auto_flush_interval该表的 region 最长多久没有 flush 就触发一次 flush字符串类型,是一个时间范围字符串,例如 '5m''1h',必须大于 0。该表选项会覆盖引擎级的 region_engine.mito.auto_flush_interval。用 ALTER TABLE 将其设为 NULL 可以移除表级覆盖、回退到引擎级配置。
max_row_group_row_countParquet row group 的最大行数字符串类型,表示 11048576010 * 1024 * 1024)之间的整数。未设置该选项时,默认值为 102400100 * 1024)。

创建自定义 row group 大小的表

CREATE TABLE IF NOT EXISTS temperatures(
ts TIMESTAMP TIME INDEX,
temperature DOUBLE DEFAULT 10
) WITH ('max_row_group_row_count' = '1024');

建议大多数用户使用默认的 row group 大小。在高级使用场景中,可以针对具体工作负载对不同的值进行基准测试以提升性能;如果单个 row group 占用的内存过大,也可以调小该值。较小的 row group 可以降低内存用量并提供更细粒度的剪枝,但会产生更多 row group 并增加元数据开销。较大的 row group 则相反。

创建指定 TTL 的表

例如,创建一个存储数据 TTL(Time-To-Live) 为七天的表:

CREATE TABLE IF NOT EXISTS temperatures(
ts TIMESTAMP TIME INDEX,
temperature DOUBLE DEFAULT 10,
) with(ttl='7d');

ttl 值是一个字符串,支持以下类型的值:

  • 时间范围字符串,如 1hour 12min 5s
  • forever, NULL, 0s (或任何长度为 0 的时间范围,如 0d)或空字符串 '',表示数据永远不会被删除。
  • instant, 注意数据库的 TTL 不能设置为 instantinstant 表示数据在插入时立即删除。对于新的 Flow workload,请避免使用 instant TTL 的 source 表,因为它们会回退到已废弃的 streaming mode;请参阅 Flow 管理文档了解更多细节。
  • 未设置,可以使用 ALTER TABLE <table-name> UNSET 'ttl' 来取消表的 ttl 设置,这样表将继承数据库的 ttl 策略(如果有的话)。

如果一张表有自己的 TTL 策略,那么它将使用该 TTL 策略。否则,数据库的 TTL 策略将被应用到表上。

比如说,如果表的 TTL 设置为 forever,那么无论数据库的 TTL 是什么,数据都不会被删除。但是如果你取消表的 TTL 设置:

ALTER TABLE <table-name> UNSET 'ttl';

那么数据库的 TTL 将会被应用到表上。

请注意表和数据库的默认 TTL 策略都是未设置,也就是没有设置 TTL,代表着数据永远不会删除。

创建自定义存储的表

或者创建一个表单独将数据存储在 Google Cloud Storage 服务上:

CREATE TABLE IF NOT EXISTS temperatures(
ts TIMESTAMP TIME INDEX,
temperature DOUBLE DEFAULT 10,
) with(ttl='7d', storage="Gcs");

创建自定义 compaction 参数的表

创建带自定义 twcs compaction 参数的表。这个表会尝试根据数据的时间戳将数据按 1 天的时间窗口分区,并会在最新时间窗口内的文件超过 8 个时合并该窗口的文件

CREATE TABLE IF NOT EXISTS temperatures(
ts TIMESTAMP TIME INDEX,
temperature DOUBLE DEFAULT 10,
)
with(
'compaction.type'='twcs',
'compaction.twcs.time_window'='1d',
'compaction.twcs.trigger_file_num'='8',
'compaction.twcs.max_output_file_size'='1GB'
);

创建 Append-Only 表

创建一个 append-only 表来关闭去重

CREATE TABLE IF NOT EXISTS temperatures(
ts TIMESTAMP TIME INDEX,
temperature DOUBLE DEFAULT 10,
) with('append_mode'='true');

创建带有 merge 模式的表

创建一个带有 last_row merge 模式的表,这是默认的 merge 模式。

create table if not exists metrics(
host string,
ts timestamp,
cpu double,
memory double,
TIME INDEX (ts),
PRIMARY KEY(host)
)
with('merge_mode'='last_row');

last_row 模式下,表会通过保留最新的行来合并具有相同主键和时间戳的行。

INSERT INTO metrics VALUES ('host1', 0, 0, NULL), ('host2', 1, NULL, 1);
INSERT INTO metrics VALUES ('host1', 0, NULL, 10), ('host2', 1, 11, NULL);

SELECT * from metrics ORDER BY host, ts;

+-------+-------------------------+------+--------+
| host | ts | cpu | memory |
+-------+-------------------------+------+--------+
| host1 | 1970-01-01T00:00:00 | | 10.0 |
| host2 | 1970-01-01T00:00:00.001 | 11.0 | |
+-------+-------------------------+------+--------+

创建带有 last_non_null merge 模式的表。

create table if not exists metrics(
host string,
ts timestamp,
cpu double,
memory double,
TIME INDEX (ts),
PRIMARY KEY(host)
)
with('merge_mode'='last_non_null');

last_non_null 模式下,表会通过保留每个字段的最新非 NULL 值来合并具有相同主键和时间戳的行。

INSERT INTO metrics VALUES ('host1', 0, 0, NULL), ('host2', 1, NULL, 1);
INSERT INTO metrics VALUES ('host1', 0, NULL, 10), ('host2', 1, 11, NULL);

SELECT * from metrics ORDER BY host, ts;

+-------+-------------------------+------+--------+
| host | ts | cpu | memory |
+-------+-------------------------+------+--------+
| host1 | 1970-01-01T00:00:00 | 0.0 | 10.0 |
| host2 | 1970-01-01T00:00:00.001 | 11.0 | 1.0 |
+-------+-------------------------+------+--------+

创建禁用 WAL 的表

创建一个禁用 WAL 的表。请注意,当 WAL 被禁用时,进程重启后尚未 flush 的数据将会丢失。

CREATE TABLE IF NOT EXISTS temperatures(
ts TIMESTAMP TIME INDEX,
temperature DOUBLE DEFAULT 10
) with('skip_wal'='true');

创建 metric engine 的物理表

Metric Engine 将多个逻辑指标表存储在共享的物理宽表中,在逻辑表之间复用列和元数据。详见 Metric Engine 架构表引擎

创建一个使用 metric engine 的物理表。

CREATE TABLE greptime_physical_table (
greptime_timestamp TIMESTAMP(3) NOT NULL,
greptime_value DOUBLE NULL,
TIME INDEX (greptime_timestamp),
)
engine = metric
with (
"physical_metric_table" = "",
);

创建一个带有跳数索引的物理表

默认情况下,metric engine 不会为列创建索引。你可以通过设置 index.typeskipping 来设置索引类型。

创建一个带有跳数索引的物理表。所有自动添加的列都将应用跳数索引。

CREATE TABLE greptime_physical_table (
greptime_timestamp TIMESTAMP(3) NOT NULL,
greptime_value DOUBLE NULL,
TIME INDEX (greptime_timestamp),
)
engine = metric
with (
"physical_metric_table" = "",
"index.type" = "skipping",
);

创建指定 SST 格式的表

创建一个使用 flat SST 格式的表。

CREATE TABLE IF NOT EXISTS metrics(
host string,
ts timestamp,
cpu double,
memory double,
TIME INDEX (ts),
PRIMARY KEY(host)
)
with('sst_format'='flat');

flat 格式针对高基数主键进行了优化,是新建表的默认 SST 格式。

列选项

GreptimeDB 支持以下列选项:

选项描述
NULL列值可以为 null
NOT NULL列值不能为 null
DEFAULT expr该列的默认值是 expr,其类型必须是该列的类型
COMMENT comment列注释,必须为字符串类型
FULLTEXT INDEX创建全文索引,可以加速全文搜索操作。仅适用于字符串类型列
SKIPPING INDEX创建跳数索引,可以加速查询稀疏数据。
INVERTED INDEX创建倒排索引,可以加速查询稠密数据。

表约束 TIME INDEXPRIMARY KEY 也可以通过列选项设置,但是它们只能在列定义中指定一次,在多个列选项中指定 PRIMARY KEY 会报错:

CREATE TABLE system_metrics (
host STRING PRIMARY KEY,
idc STRING PRIMARY KEY,
cpu_util DOUBLE,
memory_util DOUBLE,
disk_util DOUBLE,
ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP(),
TIME INDEX(ts)
);

会得到报错:

 Illegal primary keys definition: not allowed to inline multiple primary keys in columns options

正确的做法是使用 PRIMARY KEY() 来指定多个列作为主键:

CREATE TABLE system_metrics (
host STRING,
idc STRING,
cpu_util DOUBLE,
memory_util DOUBLE,
disk_util DOUBLE,
ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP() TIME INDEX,
PRIMARY KEY(host, idc),
);
Query OK, 0 rows affected (0.01 sec)

INDEX 列选项

更多关于索引配置、性能对比和使用指南的信息,请参考索引章节。

Region 分区规则

请参考 分区 章节。

CREATE EXTERNAL TABLE

Syntax

db 或当前数据库中创建新的文件外部表:

CREATE EXTERNAL TABLE [IF NOT EXISTS] [db.]table_name
[
(
column1 type1 [NULL | NOT NULL] [DEFAULT expr1] [TIME INDEX] [PRIMARY KEY] [COMMENT comment1],
column2 type2 [NULL | NOT NULL] [DEFAULT expr2] [TIME INDEX] [PRIMARY KEY] [COMMENT comment2],
...
[TIME INDEX (column)],
[PRIMARY KEY(column1, column2, ...)]
)
] WITH (
LOCATION = url,
FORMAT = { 'CSV' | 'JSON' | 'PARQUET' | 'ORC' }
[,PATTERN = regex_pattern ]
[,REGION = region ]
[,ENDPOINT = uri ]
[,ACCESS_KEY_ID = key_id ]
[,SECRET_ACCESS_KEY = access_key ]
[,ENABLE_VIRTUAL_HOST_STYLE = { TRUE | FALSE }]
[,SESSION_TOKEN = token ]
...
)

表选项

选项描述是否必需
LOCATION外部表的位置,例如 s3://<bucket>[<path>], /<path>/[<filename>]
FORMAT目标文件的格式,例如 JSON,CSV,Parquet, ORC
PATTERN使用正则来匹配文件,例如 *_today.parquet可选

S3

选项描述是否必需
REGIONAWS region 名称,例如 us-east-1
ENDPOINTThe bucket endpoint可选
ACCESS_KEY_ID用于连接 AWS S3 兼容对象存储的访问密钥 ID可选
SECRET_ACCESS_KEY用于连接 AWS S3 兼容对象存储的秘密访问密钥可选
ENABLE_VIRTUAL_HOST_STYLE如果使用 virtual hosting 访问 bucket,则设置为 true可选
SESSION_TOKEN用于连接 AWS S3 服务的临时凭证可选

时间索引列

在利用 CREATE EXTERNAL TABLE 语句创建外部表时,要求使用 TIME INDEX 约束来指定一个时间索引列。

示例

你可以在创建外部表时不带有列定义,列定义将会被自动推断:

CREATE EXTERNAL TABLE IF NOT EXISTS city WITH (location='/var/data/city.csv',format='csv');

在这个例子中,我们没有明确定义表的列,为满足外边表必须指定时间索引列的要求,CREATE EXTERNAL TABLE 语句会依据下述规则推断出时间索引列:

  1. 如果可以从文件元数据中推断出时间索引列,那么就用该列作为时间索引列。
  2. 如果存在名为 greptime_timestamp 的列(该列的类型必须为 TIMESTAMP,否则将抛出错误),那么就用该列作为时间索引列。
  3. 否则,将自动创建名为 greptime_timestamp 的列作为时间索引列,并添加 DEFAULT '1970-01-01 00:00:00+0000' 约束。

或者带有列定义:

CREATE EXTERNAL TABLE city (
host string,
ts timestamp,
cpu float64 default 0,
memory float64,
TIME INDEX (ts),
PRIMARY KEY(host)
) WITH (location='/var/data/city.csv', format='csv');

在这个例子中,我们明确定义了 ts 列作为时间索引列。如果在文件中没有适合的时间索引列,你也可以创建一个占位符列,并添加 DEFAULT expr 约束。

创建 Flow

CREATE [OR REPLACE] FLOW [ IF NOT EXISTS ] <flow-name>
SINK TO <sink-table-name>
[ EVAL INTERVAL <interval> ]
[ EXPIRE AFTER <expr> ]
[ COMMENT '<string>' ]
[ WITH (<flow-option> = <value> [, ...]) ]
AS
<SQL>;

WITH 子句用于指定 flow 选项。 例如,实验性的 experimental_enable_incremental_read 选项可以为符合条件的 batching flow 启用增量 source 读取。

对于 CREATE FLOWAS 后面的查询既可以是常规 Flow 查询,也可以是 TQL 查询。GreptimeDB 现在还支持一种严格受限的 TQL CTE 写法,用来让 Flow 定义更清晰:

CREATE FLOW calc_rate_cte
SINK TO rate_reqs
EVAL INTERVAL '1m' AS
WITH rate_data (ts, req_rate, host, job, instance) AS (
TQL EVAL (now() - '1m'::interval, now(), '30s')
rate(http_requests_total{job="my_service"}[1m])
AS req_rate
)
SELECT * FROM rate_data;

CREATE FLOW 中使用 WITH 时,当前仅支持一种刻意保持简单的形式:

  • 只能有一个 CTE,并且该 CTE 必须包含 TQL EVAL
  • 外层查询必须严格是 SELECT * FROM <cte-name>
  • 不支持额外的列投影、过滤、JOIN、排序,也不支持再混入其他 SQL CTE。
  • 如果 CTE 名称使用了引号,那么外层 SELECT 里也要用相同的带引号名称引用它。

用于创建或更新 Flow 任务,请阅读Flow 管理文档

创建 View

CREATE [OR REPLACE] VIEW [ IF NOT EXISTS ] <view-name>
AS select_statement

用于创建或更新视图,请阅读视图用户指南

创建 Trigger

请参考 CREATE TRIGGER 文档。