Lakehouse 唯一键(UNIQUE)使用说明

唯一键约束概述

UNIQUE
UNIQUE
约束用于声明表中某一列或某几列的组合值是唯一的。与主键(PRIMARY KEY)不同,UNIQUE 约束:

  • 允许列值为 NULL(主键列强制 NOT NULL);
  • 一张表可以定义多个 UNIQUE 约束(主键只能有一个);
  • 不作为实时写入(CDC UPSERT/DELETE)的操作键。

UNIQUE 约束只能在建表(CREATE TABLE)时指定,不支持通过 ALTER TABLE 添加

语法

UNIQUE 约束支持列级和表级两种写法,均可附加约束修饰符。

列级写法

CREATE TABLE t ( id int UNIQUE, name string );

表级写法

表级写法支持单列和多列组合(复合唯一键):

-- 单列 CREATE TABLE t ( id int, name string, UNIQUE(id) ); -- 复合唯一键 CREATE TABLE t ( a int, b int, UNIQUE(a, b) );

约束修饰符

UNIQUE 约束可附加三组修饰符,顺序固定(与 PRIMARY KEY、FOREIGN KEY 一致):

UNIQUE [ENABLE | DISABLE] [VALIDATE | NOVALIDATE] [RELY | NORELY]

修饰符含义默认值
ENABLE
ENABLE
/
DISABLE
DISABLE
是否对后续写入强制校验
DISABLE
DISABLE
VALIDATE
VALIDATE
/
NOVALIDATE
NOVALIDATE
是否要求数据满足约束
NOVALIDATE
NOVALIDATE
RELY
RELY
/
NORELY
NORELY
优化器是否信任并使用该约束做查询优化
RELY
RELY

不带任何修饰符时,UNIQUE 约束的默认行为是

DISABLE NOVALIDATE RELY
DISABLE NOVALIDATE RELY

默认行为:声明式约束(不去重)

默认的

DISABLE NOVALIDATE RELY
DISABLE NOVALIDATE RELY
模式下,UNIQUE 约束仅作为元数据记录,不阻止重复值写入

CREATE TABLE uk_demo (id int UNIQUE, name string); -- 查看约束 DESC EXTENDED uk_demo; -- unique_keys: ((id) DISABLE NOVALIDATE RELY) -- 重复 id 均可写入 INSERT INTO uk_demo VALUES(1, 'a'); INSERT INTO uk_demo VALUES(1, 'b'); SELECT * FROM uk_demo; -- 1 | a -- 1 | b (重复值未被阻止) -- 允许多个 NULL INSERT INTO uk_demo VALUES(NULL, 'c'); INSERT INTO uk_demo VALUES(NULL, 'd'); -- 均写入成功

RELY 与优化器

RELY
RELY
(默认)告诉优化器可以信任该约束并据此优化查询,即使约束并未在写入时强制校验。优化器会利用 RELY 的唯一键进行:

  • 去重消除(DISTINCT / GROUP BY 的化简);
  • 行数与 NDV(distinct value 数)估算;
  • Join 基数估算与计划选择。

如果数据实际上并不满足唯一性,而约束又声明为 RELY,可能导致优化器产生错误的结果。此时应使用

NORELY
NORELY
让优化器忽略该约束:

CREATE TABLE uk_demo (id int UNIQUE NORELY, name string); -- unique_keys: ((id) DISABLE NOVALIDATE NORELY)

修饰符的实际生效情况

实测中各修饰符组合的实际行为如下:

声明方式DESC EXTENDED 显示SQL 写入行为
UNIQUE
UNIQUE
(默认)
DISABLE NOVALIDATE RELY
DISABLE NOVALIDATE RELY
允许重复、允许多个 NULL
UNIQUE ENABLE
UNIQUE ENABLE
ENABLE NOVALIDATE RELY
ENABLE NOVALIDATE RELY
允许重复(无 VALIDATE 不校验)
UNIQUE NORELY
UNIQUE NORELY
DISABLE NOVALIDATE NORELY
DISABLE NOVALIDATE NORELY
允许重复,且优化器忽略
多个
UNIQUE
UNIQUE
各自
DISABLE NOVALIDATE RELY
DISABLE NOVALIDATE RELY
允许

与主键(PRIMARY KEY)的关系

  • 表的主键会同时被记录为一个唯一键,因此
    DESC EXTENDED
    DESC EXTENDED
    unique_keys
    unique_keys
    中会包含主键列。
  • 一张表可以同时定义主键和多个(非强制的)UNIQUE 约束。
  • 一张表最多只能有一个强制约束。如果主键已是强制的(默认即强制),再声明
    UNIQUE ... ENABLE VALIDATE
    UNIQUE ... ENABLE VALIDATE
    会在建表时报错:

CREATE TABLE t (id int PRIMARY KEY, code int UNIQUE ENABLE VALIDATE); -- CZLH-42000: cannot enforce UNIQUE constraint with an enforced PRIMARY KEY

对比项PRIMARY KEYUNIQUE
每表数量至多 1 个可多个
列可空性强制 NOT NULL允许 NULL(可多个 NULL)
实时写入(CDC)去重键
默认修饰符
ENABLE VALIDATE RELY
ENABLE VALIDATE RELY
DISABLE NOVALIDATE RELY
DISABLE NOVALIDATE RELY
主要用途CDC 去重 + 查询优化查询优化(声明式)

建表时的校验规则

建表时系统会对 UNIQUE 约束做以下校验:

  • 同一约束内列名不能重复
    UNIQUE(a, a)
    UNIQUE(a, a)
    报错。
  • 约束不能冗余:若某个 UNIQUE 约束与主键相同、或是另一个唯一键(或主键)的超集,会报
    unnecessary unique key
    unnecessary unique key
  • 至多一个强制约束:多个
    ENABLE VALIDATE
    ENABLE VALIDATE
    约束(含主键)会报错。

使用建议

  • 把 UNIQUE 当作给优化器的提示:当你确知某列在业务上唯一(如从上游系统同步的业务主键),用 UNIQUE 声明可以帮助优化器生成更优的计划。
  • 若声明的列实际可能存在重复,使用
    NORELY
    NORELY
    避免优化器据此做错误化简。
  • 需要在写入时真正强制去重时,使用主键(PRIMARY KEY)并配合实时写入接口,而不是 UNIQUE 约束。

参考

联系我们
预约咨询
微信咨询
电话咨询
邮件咨询