SET

表示无序的、唯一元素的集合。集可能只包含基元类型。与数组不同,在集中,元素位置是没有意义的。

集不支持 LONG 类型(如 LONG VARBINARY 或 LONG VARCHAR)或用户定义类型(如 Geometry)。

如果您从数组填充集,Vertica 会对值进行排序并移除重复元素。如果您不关心元素位置并计划运行检查特定元素是否存在的查询(查找、包含),则使用集可以提高查询性能。

集可以是有界的(这意味着它们指定了最大元素计数),也可以是无界的。无界集具有最大二进制大小,可以显式设置或默认设置。请参阅元素计数和集合大小的限制

语法

列定义中:


SET[data_type, max_elements] |
SET[data_type](max_size) |
SET[data_type]

字面量中:

SET[value[, ...] ]

限制

  • 集仅支持基元类型的数据,例如 int、UUID 等。

  • 如果指定了边界,则会对加载或更改数据的所有操作强制执行边界。无界集可以具有适合所分配的二进制大小的任意数量的元素。

  • 集具有最大二进制大小。如果在定义集时未设置此大小,则使用默认值。

列定义的语法

列定义中使用的集可以是有界或无界的。有界集必须指定最大元素数。无界集可以指定集的最大二进制大小,也可以使用 DefaultArrayBinarySize 的值。您可以指定边界或二进制大小,但不能同时指定两者。有关这些值的更多信息,请参阅元素计数和集合大小限制

以下示例定义了一个具有无界集列的表。

=> CREATE TABLE users
(
user_id INTEGER,
display_name VARCHAR,
email_addrs SET[VARCHAR]
);

当您将数组数据加载到定义为集的列中时,数组数据会自动转换为集。

直接构造的语法(字面量)

使用 SET 关键字构造集值。字面量设置值包含在括号中。例如,要创建一个 INT 集,您将执行以下操作:

=> SELECT SET[1,2,3];
  set
-------
 [1,2,3]
(1 row)

您可以通过转换将数组显式转换为集,如以下示例所示:

=> SELECT ARRAY[1, 5, 2, 6, 3, 0, 6, 4]::SET[INT];
     set
-----------------
[0,1,2,3,4,5,6]
(1 row)

请注意,重复元素已移除并且元素已排序。

因为在直接构造集时元素是已知的,所以这些集是隐式有界的。

输出格式

集以类似 JSON 的格式显示,括号中包含逗号分隔的元素(如数组)。在以下示例中,email_addrs 列是一个集。

=> SELECT custkey,email_addrs FROM customers LIMIT 4;
 custkey |                           email_addrs
---------+------------------------------------------------------------------------
 342176  | ["joe.smith@example.com"]
 342799  | ["bob@example,com","robert.jones@example.com"]
 342845  | ["br92@cs.example.edu"]
 342321  | ["789123@example-isp.com","sjohnson@eng.example.com","sara@johnson.example.name"]

元素计数和集合大小的限制

在为表列声明集合类型时,您可以限制元素的数量或集合的总二进制大小。在查询处理期间,Vertica 始终根据元素计数或二进制大小保留列所需的最大内存。如果此大小比您的数据实际需要的大得多,则设置这些限制之一可以通过减少必须为列保留的内存量来提高查询性能。

您可以通过强制转换来更改集合的边界,包括在有界和无界集合之间进行更改。请参阅 强制转换

有界集合指定最大元素计数。有界集合列中的值可能包含较少的元素,但可能不会包含更多。任何将比声明的最大值更多的元素插入有界集合的尝试都是错误的。有界集合的二进制大小是数据类型大小和最大元素数的乘积,可能向上取整。

无界集合显式或隐式指定二进制大小(以字节为单位)。它可能包含尽可能多的元素,以适应该二进制大小。

您可以为无界集合指定最大二进制大小,而不是指定边界。无论集合包含多少元素,二进制大小都是绝对限制。未指定最大二进制大小的集合使用 DefaultArrayBinarySize 的值。此大小在定义集合时设置,不受以后对 DefaultArrayBinarySize 值的更改的影响。

您不能为有界集合设置最大二进制大小,只能设置无界集合。

比较

所有集合都支持相等 (=)、不等 (<>) 和 null 安全相等 (<=>)。一维集合还支持以下集合之间的比较运算符 (<<=>>=) 相同的类型(数组或集合)。比较遵循以下规则:

  • 空集合最后排序。

  • 使用元素数据类型的排序规则逐个元素比较非空集合。第一对不相等元素的相对顺序决定了两个集合的顺序。

  • 如果两个集合中的所有元素都等于较短集合的长度,则较短集合在较长集合之前排序。

  • 如果两个集合中的所有元素相等且集合的长度相等,则集合相等。

Null 处理

集合的空语义在大多数方面与普通列一致。有关空处理的更多信息,请参阅 NULL 排序顺序

当集合为 null 而不是空时,空安全相等运算符 (<=>) 的行为与相等 (=) 不同。将集合严格地与 NULL 进行比较是未定义的。

=> SELECT ARRAY[1,3] = NULL;
?column?
----------

(1 row)

=> SELECT ARRAY[1,3] <=> NULL;
 ?column?
----------
 f
(1 row)

在以下示例中,表中的授予列对于员工 99 为 null。

=> SELECT grants = NULL FROM employees WHERE id=99;
 ?column?
----------

(1 row)

=> SELECT grants <=> NULL FROM employees WHERE id=99;
 ?column?
----------
 t
(1 row)

空集合不为 null 并且按预期运行。

=> SELECT ARRAY[]::ARRAY[INT] = ARRAY[]::ARRAY[INT];
 ?column?
----------
 t
(1 row)

集合逐个元素进行比较。如果比较依赖于 null 元素,则结果是未知的 (null),而不是 false。例如,ARRAY[1,2,null]=ARRAY[1,2,null]ARRAY[1,2,null]=ARRAY[1,2,3] 都返回 null,但 ARRAY[1,2,null]=ARRAY[1,4,null] 因为第二个元素不匹配而返回 false。

强制转换

转换一个集会转换集的每个元素。因此,您可以按照与标量值转换相同的规则在数据类型之间转换。

您可以显式地转换字面量集和集列:

=> SELECT SET['1','2','3']::SET[INT];
   set
---------
[1,2,3]
(1 row)

=> CREATE TABLE transactions (tid INT, prod_ids SET[VARCHAR], quantities SET[VARCHAR(32)]);

=> INSERT INTO transactions VALUES (12345, SET['p1265', 'p4515'], SET['15','2']);

=> SELECT quantities :: SET[INT] FROM transactions;
 quantities
------------
   [15,2]
(1 row)

赋值转换和隐式转换的工作方式与标量相同。

您可以在 ARRAY 和 SET 类型之间执行显式转换,但不能执行隐式转换。如果集合是无界的且数据类型未更改,则保留二进制大小。例如,如果将 ARRAY[INT] 转换为 SET[INT],则该集与数组具有相同的二进制大小。

在将数组转换为集时,Vertica 会首先转换每个元素,然后对集进行排序并移除重复项。如果将两个源值转换为相同的目标值,则其中一个将被移除。例如,如果您将 FLOAT 数组转换为一组 INT,则数组中的两个值可能会四舍五入为相同的整数,然后被视为重复项。如果数组包含多个转换为 NULL 的值,也会发生这种情况。

如果从一种元素类型转换为另一种元素类型,则生成的集合使用默认二进制大小。如果这会导致数据不适合,则转换失败。

函数和运算符

有关可用于操作数组和集合的函数的完整列表,请参阅 集合函数

可以通过以下方式使用集合:

集合不能以下列方式使用:

  • 作为 IN 或 NOT IN 表达式的一部分。

  • 创建表时作为分区列。

  • 使用 ANALYZE_STATISTICS 或 TopK 预测。

  • 仅限非原生数组:ORDER BY、PARTITION BY、DEFAULT、SET USING 或约束。