表是存储和组织数据的基本单位,合理地创建表、设置表索引及属性,可以为您提供高效的数据处理和分析能力。本文为您介绍在Hologres中的建表语法、设置索引和HoloWeb可视化建表。
建表语法
命令格式
Hologres的建表语法兼容PostgreSQL,通过CREATE TABLE语句创建表,具体语法如下。
说明当前Hologres DDL支持多行事务,V2.0版本起支持多行DML混合事务。
V2.1版本起支持
create table with property
语法,简化设置表属性方法。
推荐优先使用
CREATE TABLE WITH
语法,针对特定场景,如频繁创建已存在的表(CREATE TABLE IF NOT EXISTS
)并设置表属性时,可以显著提升DDL性能。V2.1版本起支持的语法:
BEGIN; CREATE TABLE [ IF NOT EXISTS] [schema_name.] table_name ([ { column_name column_type [column_constraints, [...]] | table_constraints [,...] } ]) [WITH ( property = 'value', [, ...] )] ; COMMENT ON COLUMN < tablename.column > IS 'value'; COMMENT ON TABLE < tablename > IS 'value'; COMMIT;
所有版本都支持的语法:
begin; create table [if not exists] [schema_name.]table_name ([ { column_name column_type [column_constraints, [...]] | table_constraints [, ...] } ]); call set_table_property('<table_name>', property, value); comment on column <tablename.column> is 'value'; comment on table <tablename> is 'value'; commit;
合理的建表索引总结
Hologres是兼容PostgreSQL生态,建表语法与PostgreSQL相同,但是索引与PostgreSQL不同,Hologres支持的索引请参见设置表属性和索引。建表时选择合适的索引,能够使SQL在执行时快速命中数据,减少IO消耗,以更少的计算资源,实现更快的查询性能。下图是一个SQL从发起到获取数据的执行流程,可以通过下图理解每个索引的作用,以方便实际业务中更加方便高效的为表选择合适的索引。
SQL执行时,如果是分区表,那么会通过分区裁剪,定位到所在分区。
通过Distribution Key快速定位到数据所在的数据分片(Shard)。
通过Event Time Column(原Segment Key)快速定位到数据所在的文件。
Clustering Key为数据在文件内的排序,可以通过Clustering Key快速定位到所在的文件块。
位图索引Bitmap是文件内的索引,可以通过Bitmap快速定位到符合条件的数据所在的行号。
索引适用的场景如下。
索引 | 适用场景 | 示例查询语句 |
Distribution Key | 适合于频繁进行Group By的列或者多表Join时的Join字段设置为Distribution Key,能够减少数据Shuffle,实现Local Join的能力。 |
|
Clustering Key | 将范围查询或Filter查询列作为聚簇索引列。索引过滤具备左匹配原则,建议设置聚簇索引列不要超过两列。 |
|
Bitmap | 将等值查询列作为Bitmap列。 |
|
Event Time Column(原Segment_Key) | 适用于将日志、流量等和时间强相关的列设置为Segment_Key。 |
|
设置表属性和索引
在Hologres中,可以通过set_table_property
或create table with
命令为表设置多种属性,合理的表属性设置可以有助于系统高效地组织和查询数据。与数据存储布局有关的参数需要和建表语句同时执行。
命令格式
-- 2.1版本起支持 create table <table_name> (...) with (property = 'value'[, ...]); -- 所有版本支持 call set_table_property('<table_name>', property, 'value');
说明set_table_property
的调用需要与create table
在同一事务中执行。Hologres支持的设置表属性如下所示,包括但不限于以下几种表属性。
V2.1版本起支持的语法:
CREATE TABLE <table_name> (...) WITH ( orientation = '[column | row | row,column]', table_group = '[tableGroupName]', distribution_key = 'columnName[,...]]', clustering_key = '[columnName{:asc]} [,...]]', event_time_column = '[columnName [,...]]', bitmap_columns = '[columnName [,...]]', dictionary_encoding_columns = '[columnName [,...]]', time_to_live_in_seconds = '<non_negative_literal>' [,storage_mode, ...] );
所有版本都支持的语法:
BEGIN; CREATE TABLE <table_name> (...); call set_table_property('table_name', 'orientation', '[column | row]'); call set_table_property('table_name', 'table_group', '[tableGroupName]'); call set_table_property('table_name', 'distribution_key', '[columnName[,...]]'); call set_table_property('table_name', 'clustering_key', '[columnName{:asc]} [,...]]'); call set_table_property('table_name', 'event_time_column', '[columnName [,...]]'); call set_table_property('table_name', 'bitmap_columns', '[columnName [,...]]'); call set_table_property('table_name', 'dictionary_encoding_columns', '[columnName [,...]]'); call set_table_property('table_name', 'time_to_live_in_seconds', '<non_negative_literal>'); COMMIT;
参数说明
具体参数和相关内容如下表所示:
参数
说明
列存表
行存表
行列共存表
建议值
建表后是否可修改
orientation
表存储格式。
column(默认值)
row
row,column
column
否,如需修改请重新建表。
table_group
Table Group。
默认为default table group。
默认为default table group。
默认为default table group。
默认即可。
否,如需修改请重新建表或者Resharding。
distribution_key
分布键。
默认为主键,根据业务场景修改。
默认为主键。
默认为主键。
主键的子集,建议只选择一列。
否,如需修改请重新建表。
clustering_key
聚簇索引。
默认为空。
默认为主键。
默认为空。
建议最多选择一列,且仅支持asc序。
否,如需修改请重新建表。
event_time_column
分段键。
默认为第一个非空时间戳字段。
不支持。
默认为第一个非空时间戳字段。
建议时间戳字段。
否,如需修改请重新建表。
bitmap_columns
位图索引。
按需使用。
不支持。
按需使用。
建议用于等值比较的列,一般10列以下。
是,详情请参见ALTER TABLE。
dictionary_encoding_columns
比特编码。
按需使用。
不支持。
按需使用。
建议低基数列,一般10列以下。
是,详情请参见ALTER TABLE。
time_to_live_in_seconds
表数据生命周期。
按需使用。
按需使用。
按需使用。
默认即可,无需设置。
是,详情请参见ALTER TABLE。
orientation
指定了数据库表在Hologres中的存储模式是列存还是行存,从V1.1版本开始支持行列共存的格式,命令语法如下所示。不同的存储格式适用于不同的查询场景,建表时默认为列存,其余存储模式需要建表时显式指定,详情请参见表存储格式:列存、行存、行列共存。
call set_table_property('table_name', 'orientation', '[column | row |row,column]');
table_group
在Hologres中,Shard是指数据分片,Table Group是Hologres中特有的逻辑存储概念,用于管理Shard数,一个Table Group唯一对应一组Shard。新建数据库后,如果没有创建新的Table Group,那么创建第一个表时,会自动建立一个名称为
<db>_tg_default
的默认Table Group,后续表创建时没有指定Table Group将会被指定至默认Table Group中。一般情况下无需设置Table Group,使用默认Table Group即可,当实例规格较大(大于256 Core时),建议根据业务情况划分不同的Table Group和Shard数,带来更好的性能,使用详情请参见Table Group与Shard Count操作指南。call set_table_property('table_name', 'table_group', '[tableGroupName]');
distribution_key
设置分布键Distribution Key。Distribution Key指定了表的分布策略,数据根据Distribution Key被分配到各个Shard上,保证Distribution Key相同的记录会被分配到同一个Shard上。Distribution Key是非常重要的分布式概念,合理的设置Distribution Key可以提高查询性能和QPS等,详情请参见分布键Distribution Key。
call set_table_property('table_name', 'distribution_key', '[columnName[,...]]');
clustering_key
设置聚簇索引Clustering Key,命令语法如下所示。Hologres会根据Clustering Key在文件内对数据进行排序,默认为升序(acs)排序。合理地设置Clustering Key能够加速在索引列上的Range和Filter查询,提升查询性能,详情请参见聚簇索引Clustering Key。
call set_table_property('table_name', 'clustering_key', '[columnName{:asc} [,...]]');
event_time_column
设置分段键Event_time_column (原Segment Key),命令语法如下所示。文件会根据Event_time_column划分,当命中Event_time_column时,可以快速定位到数据所在的文件,Event_time_column适用于数据为单调递增或单调递减的有序字段,例如时间戳字段,非常适用于日志、流量等和时间强相关的数据,合理设置可极大提升查询性能,详情请参见Event Time Column(Segment Key)。
call set_table_property('table_name', 'event_time_column', '[columnName [,...]]');
bitmap_columns
设置位图索引Bitmap,命令语法如下所示。Bitmap能够快速定位到符合条件数据所在的行号,适合将等值查询条件的数据设置为位图索引列。默认列存表所有TEXT数据类型的字段都会被隐式地设置为位图索引列,详情请参见位图索引Bitmap。
call set_table_property('table_name', 'bitmap_columns', '[columnName{:[on|off]}[,...]]');
dictionary_encoding_columns
设置字典编码Dictionary Encoding,命令语法如下所示。Dictionary Encoding指定列的值构建字典映射。字典编码可以将字符串的比较转成数字的比较,加速Group By、Filter等查询。默认列存表所有TEXT数据类型的字段都会被设置为Dictionary Encoding列 ,在Hologres V0.9及之后版本,会根据数据特征自动选择是否创建字典编码。
call set_table_property('table_name', 'dictionary_encoding_columns', '[columnName{:[on|off|auto]}[,...]]');
time_to_live_in_seconds(不建议使用)
设置表的数据生命周期(TTL),单位为秒,命令语法如下所示。
TTL过期时间是按照数据写入的时间开始计算,不是按照数据更新时间计算。不设置TTL的时候,默认为100年,Hologres从 V1.3.24版本开始,TTL允许的最小值是一天,即86400秒。TTL的详细使用说明请参见SQL命令列表。
TTL不是精确的时间,即到期了之后数据会在某一段时间(不是固定时间)删除(只删除数据,表还会存在),因此可能会出现PK重复的问题。生产业务不建议使用TTL来管理数据的生命周期,建议使用CREATE PARTITION TABLE。
call set_table_property('table_name', 'time_to_live_in_seconds', '<non_negative_literal>');
使用限制
支持将多个字段设置为Primary Key(即复合主键),被设置为Primary Key的字段是唯一且非空,同时只能在一个语句里设置多列为表的Primary Key。Primary Key必须为not nullable的列或者列组合,不支持将Float、Double、Numeric、Array、Json、Date及其他复杂数据类型的字段设为Primary Key。不支持修改Primary Key,如需修改请重新建表。如下示例指导您将id和ds设置为表的Primary Key。
BEGIN; CREATE TABLE public.test ( "id" text NOT NULL, "ds" text NOT NULL, PRIMARY KEY (id,ds) ); CALL SET_TABLE_PROPERTY('public.test', 'orientation', 'column'); COMMIT;
列约束
column_constraints
和表约束table_constraints
的支持情况如下。参数
column_constraints
table_constraints
primary key
支持
支持
not null
支持
-
null
支持
-
unique
不支持
不支持
check
不支持
不支持
default
支持
不支持
关键字、保留字、系统字段、特殊字符、大小写需使用双引号("")进行转义。
Hologres对列名、表名等关键字的限制包括:列名称不能以
hg_
开头,Schema名称不能以holo_
、hg_或
pg_
开头。同时还需要遵循PostgreSQL本身的关键字、保留字、系统字段规范,详情请参见关键词列表、系统列列表,这些PostgreSQL关键词作为列名时需要加双引号("")进行转义。表名和列名均对大小写不敏感,如需定义大写表名、大写列名、特殊字符表名或列名、以数字开头的表名或列名时,可使用双引号("")进行转义。
如果有自定义字段与系统字段名称重复,可能会报错,例如
ctid
。Hologres V2.0版本起优化了设置表属性时使用双引号("")进行转义的语法。如果需要对列名进行转义,则需要使用新的语法。如果您仍希望使用旧语法,需要开启如下GUC。
-- session级别开启旧语法开关 set hg_disable_parse_holo_property = on; -- DB级别开启旧语法开关 alter database <db_name> set hg_disable_parse_holo_property = on;
示例如下:
说明在查询列名称以数字开头的列时,同样需要使用双引号("")进行转义,否则会出现列名解析错误的情况。
create table "TBL" (a int); select relname from pg_class where relname = 'TBL'; insert into "TBL" values (-1977); select * from "TBL"; ------------------------------------------------------------------ -- Hologres V2.0版本起,为需要转义的列设置表属性的语法 begin; create table tbl (c1 int not null); call set_table_property('tbl', 'clustering_key', '"c1":asc'); commit; -- Hologres V2.0版本前,为需要转义的列设置表属性的语法 begin; create table tbl (c1 int not null); call set_table_property('tbl', 'clustering_key', '"c1:asc"'); commit; ------------------------------------------------------------------ -- Hologres V2.1版本起,为多列(包含大写)设置表属性的语法 begin; create table tbl ("C1" int not null, c2 text not null) with (clustering_key = '"C1",c2'); commit; -- Hologres V2.0版本起,为多列(包含大写)设置表属性的语法 begin; create table tbl ("C1" int not null, c2 text not null); call set_table_property('tbl', 'clustering_key', '"C1",c2'); commit; -- Hologres V2.0版本前,为多列(包含大写)设置表属性的语法 begin; create table tbl ("C1" int not null, c2 text not null); call set_table_property('tbl', 'clustering_key', '"C1,c2"'); commit; ------------------------------------------------------------------ create table "Tab_$A%*" (a int); select relname from pg_class where relname = 'Tab_$A%*'; insert into "Tab_$A%*" values (-1977); select * from "Tab_$A%*"; ------------------------------------------------------------------ create table tbl ("2c" int not null); insert into tbl values (3), (4); select "2c" from tbl;
在创建表时,如果不存在同名表且语义正确,表创建都会返回成功。如果不指定
IF NOT EXISTS
选项而存在同名表,则返回异常。如果指定IF NOT EXISTS
选项,Hologres会提示信息,跳过表创建步骤,返回成功,直观的规则如下。配置项
指定if not exists
不指定if not exists
存在同名表
NOTICE:relation “xx“already exists,skippingSUCCEED
ERROR:relation is already exists.
不存在同名表
SUCCEED
SUCCEED
表名称的长度不能超过64字节,超过64字节将被截断。
暂时不支持修改数据类型,如需修改,请重新建表。
行存表必须设置主键,行列共存表必须设置主键,列存表主键可选。
不支持调整列顺序,如需调整,请重新建表。
orientation、distribution_key、clustering_key、event_time_column属性决定了数据写入后的存储布局,因此建表后不支持更改,如需修改,需要重新建表;bitmap和dictionary属性不影响数据存储布局,可以在建表后按需更改。
不支持将已有表的非空(
not null
)字段改成空(nullable
)字段,同时不支持将nullable
的字段改为not null
的字段,如需更改请重新建表。
查看表结构
您可以执行如下命令查看TABLE的具体DDL:
create extension hg_toolkit; --该命令是DB级别,一个DB执行一次即可
select hg_dump_script('[<schema_name>.]<table_name>');
您也可以通过HoloWeb,在元数据管理模块进行DDL查看。
为提升建表的便捷性和可阅读性,从Hologres V2.2版本开始,
hg_dump_script
返回的表属性从原CALL语法更改为WITH语法。
使用示例
新建普通列存表并指定Primary Key。
说明Distribution Key必须是Primary Key的子集。
begin; CREATE TABLE tbl ( "id" bigint NOT NULL, "name" text NOT NULL, "age" bigint, "class" text NOT NULL, "reg_timestamp" timestamptz NOT NULL, PRIMARY KEY (id,age) ); call set_table_property('tbl', 'orientation', 'column'); call set_table_property('tbl', 'distribution_key', 'id'); call set_table_property('tbl', 'clustering_key', 'age'); call set_table_property('tbl', 'event_time_column', 'reg_timestamp'); call set_table_property('tbl', 'bitmap_columns', 'name,class'); call set_table_property('tbl', 'dictionary_encoding_columns', 'class:auto'); commit;
新建分区表并指定Primary Key。
说明分区表有主键时,主键里面必须包含分区字段。
begin; CREATE TABLE www ( name text NOT NULL, ds text NOT NULL, age text NOT NULL, PRIMARY KEY (name,ds) ) PARTITION BY LIST(ds); CALL SET_TABLE_PROPERTY('www', 'orientation', 'column'); commit;
分区表还需要创建分区子表,详情请参见CREATE PARTITION TABLE。
新建普通表并设置默认值。
begin; CREATE TABLE tbl_default ( smallint_col smallint DEFAULT 0, int_col int DEFAULT 0, bigint_col bigint DEFAULT 0, boolean_col boolean DEFAULT FALSE, float_col real DEFAULT 0.0, double_col double precision DEFAULT 0.0, decimal_col decimal(2, 1) DEFAULT 0.0, text_col text DEFAULT 'N', char_col char(2) DEFAULT 'N', varchar_col varchar(200) DEFAULT 'N', timestamptz_col timestamptz DEFAULT now(), date_col date DEFAULT now(), timestamp_col timestamp DEFAULT now() ); commit;
HoloWeb可视化新建内部表
HoloWeb提供可视化一键建表功能,无需写SQL命令就能创建表,步骤如下。
进入HoloWeb页面,详情请参见连接HoloWeb并执行查询。
在HoloWeb页面顶部菜单栏,单击
。您也可以在元数据管理界面的已登录实例列表。单击目标数据库,鼠标右击数据库下已创建的目标模式,选择新建内部表。
在新建内部表页面,配置各项参数。
在页面右上角,单击提交。提交之后,您可以在左侧对应模式下,刷新出新建的内部表。
其他相关操作:
编辑内部表
在元数据管理界面的已登录实例列表,双击目标内部表。
在目标内部表信息页,单击编辑表,可以添加字段、更改表数据周期等部分表属性。
单击提交。
删除内部表
在元数据管理界面的已登录实例列表,鼠标右击目标内部表,选择删除表。
在删除表对话框,单击确认。
表数据预览
在已登录实例列表,双击目标内部表。
进入表信息页签,单击数据预览,则可以预览表数据。
DDL预览
在目标表信息页签,单击DDL语句,则可以预览DDL语句。
下一步
创建完表之后,您可以通过数据插入(INSERT 语句)、数据同步和数据迁移实现数据导入,详情请参见INSERT、数据同步概述和导出。
相关文档
根据已有表创建新表,您可以选择复制表结构和表数据,详情请参见CREATE TABLE AS;也可以选择复制表结构和表属性,详情请参见CREATE TABLE LIKE。
创建分区表请参见CREATE PARTITION TABLE。
创建外部表请参见CREATE FOREIGN TABLE。
修改表属性请参见ALTER TABLE。