产品指南
表结构设计

表结构设计

CREATE TABLE 语句用于在数据库中创建新表。以下是一些指引,以帮助您在 ProtonBase 中创建新表。

表的存储模式

ProtonBase 中的表包括三种存储模式:行存、列存和行列混存。每种存储方式都有其自己的优点和用途。

  • 行存: 在行存下,单个行的数据存储在一起。这是传统关系数据库最常见的布局。表的默认存储方式是行存。
  • 列存: 在列存下,每列的数据存储在一起。列存对于分析工作负载非常高效,因为您通常查询特定列而不是所有数据。它可以减少 I/O 并提高查询性能。
  • 行列混存: 在某些情况下,您可能选择行列混存,结合了行存和列存。这在处理各种查询,如 HTAP 场景时,可能会有益。请注意,行列混存下的存储会更大。

表存储模式的选择取决于您应用程序的特定要求和查询模式。

-- 创建一张行存表 (默认存储模式).
CREATE TABLE row_t(
    id int PRIMARY KEY,
    name text,
    age smallint,
    gender char(1)
);
 
-- 创建一张列存表
CREATE TABLE columnar_t(
    id int PRIMARY KEY,
    name text,
    age smallint,
    gender char(1)
) USING columnar;
 
-- 创建一张行列混存表
CREATE TABLE hybrid_t(
    id int PRIMARY KEY,
    name text,
    age smallint,
    gender char(1)
) USING hybrid;

更多有关建表的语法说明,请参考CREATE TABLE

定义主键

主键(Primary Key,PK)是表中每一行的唯一标识符。大多数情况下,为了确保数据的唯一性和完整性,会在表上定义主键。设置主键时,请考虑以下事项:

  • 唯一性:主键必须包含每一行的唯一值。ProtonBase 会自动强制执行此要求。
  • 效率:选择一个经常用于查询和连接表的列或一组列。这有助于优化查询性能。如果主键中包含多列,主键中列的顺序会显著影响底层索引查找的效率。只有在先导列(最左侧)上存在约束时才会高效。具体规则是,在先导列上的等值约束,加上第一个不等值约束的列上的不等值约束,将被用于限制索引被扫描的部分。例如,假设主键是(a,b,c),查询条件为 WHERE a = 5 AND b >= 42 AND c < 77,那么索引将从具有 a = 5 和 b = 42 的第一个条目扫描,一直到具有 a = 5 的最后一个条目。
  • 稳定性:尽量避免那些可能经常更改的列作为主键,因为这可能导致更新变慢。 要设置主键,请在表定义中使用 PRIMARY KEY 约束:
CREATE TABLE t(
    id int PRIMARY KEY,
    name text,
    age smallint,
    gender char(1)
);

在定义主键时,应避免以下一些不好的示例:

  • 不要总是将自增 id 字段作为主键,特别是当 id 字段实际上并未在用户的所有查询中使用时。自增 id 字段会影响写入性能。
  • 不要在单一单调列上定义主键,例如在自增列或按时间戳递增的列上,这会影响写入性能。

行存表

行存是表的默认模式,或者您也可以使用 using row 来指定表为行存。

CREATE TABLE row_t(
    id int PRIMARY KEY,
    name text,
    age smallint,
    gender char(1)
);
 
CREATE TABLE row_t(
    id int PRIMARY KEY,
    name text,
    age smallint,
    gender char(1)
) USING row;

列存表

您也可以使用 using columnar 来指定表为列存。

CREATE TABLE columnar_t(
    id int PRIMARY KEY,
    name text,
    age smallint,
    gender char(1)
) USING columnar;

行列混存表

您也可以使用 using hybrid 来指定表为行列混存。

CREATE TABLE hybrid_t(
    id int PRIMARY KEY,
    name text,
    age smallint,
    gender char(1)
) USING hybrid;

CREATE TABLE LIKE

基于现有表的表结构创建一个空表。创建一个空表,复制目标表的结构以及约束,如 NOT NULL。CREATE TABLE LIKE语法通常用于数据库管理和维护任务,例如在一个数据库中创建与另一个表相同结构的临时表,或者将表的结构复制到另一个 schema 下。

CREATE TABLE t2(LIKE t INCLUDING ALL);

创建的时候,您可以同时指定表的存储模式:

CREATE TABLE t2(LIKE t INCLUDING ALL) USING columnar;
CREATE TABLE t2(LIKE t INCLUDING ALL) USING hybrid;

CREATE TABLE AS SELECT(CTAS)

SELECT语句创建表,使用CREATE TABLE AS SELECT语句,您可以复制整个表、特定记录或仅表的结构。请注意,这个命令无法复制索引或约束,如 NOT NULL、主键、外键等。

CREATE TABLE t2 AS SELECT * FROM t WHERE age > 18;

自增表

要创建一个具有自动递增主键的表,您可以使用 SERIAL 数据类型作为主键列的数据类型(注:serial 确保了单调递增,但是会影响写入性能。尽量选用业务字段作为主键)。以下是一个示例:

> CREATE TABLE t(id serial PRIMARY KEY, b int);
CREATE TABLE
> INSERT INTO t(b) VALUES (1), (2), (4);
INSERT 0 3
> SELECT * FROM t;
 id | b
----+---
  1 | 1
  2 | 2
  3 | 4
(3 rows)

外键表

要创建一个具有外键约束的表,您可以使用以下示例。假设您有两个表,一个名为 "weather",另一个名为 "cities",并且您想确保在 "weather" 表中插入的行必须有一个在 "cities" 表中匹配的条目。

CREATE TABLE cities (
        name     varchar(80) PRIMARY KEY,
        location point
);
 
CREATE TABLE weather (
        city      varchar(80) REFERENCES cities(name),
        temp_lo   int,
        temp_hi   int,
        prcp      real,
        date      date
);

分区表

分区通常用于提高查询性能和更有效地管理大量数据。分区表的介绍及例子详见这里

修改表结构

支持在线修改表结构,简化运维工作,具体参考文档表结构修改