将数据批量加载到 Flex 表中
您可以指定下列 Flex 解析器之一,并使用 COPY 语句将数据批量加载到 Flex 表中:
-
FAVROPARSER
-
FCEFPARSER
-
FCSVPARSER
-
FDELIMITEDPAIRPARSER
-
FDELIMITEDPARSER
-
FJSONPARSER
-
FREGEXPARSER
所有 Flex 解析器均将数据存储为单值 VMap。它们驻留在 VARBINARY__raw__
列,该列为具有 NOT NULL 约束的实际列。VMap 编码为单一二进制值,以便存储在 __raw__
列中。编码将值字符串置于连续区块中,后面是键字符串。Vertica 针对带 NULL 指定列的键,支持 VMap 内的 NULL 值。键和值字符串分别代表 Flex 表中的虚拟列和它们的值。
如果 Flex 表数据行太大而无法适应 __raw__
列,该数据行将被拒绝。默认情况下,被拒数据和异常文件存储在标准 CopyErrorLogs
位置,这是编录目录的一个子目录:
v_mart_node003_catalog/CopyErrorLogs/trans-STDIN-copy-from-exceptions.1
v_mart_node003_catalog/CopyErrorLogs/trans-STDIN-copy-rejections.1
出于对磁盘空间的考虑,Flex 表不会复制任何被拒数据。被拒数据文件存在,但对于每个被拒记录,仅包含一个换行符。相应的异常文件列出了每个记录被拒绝的原因。
您可以为被拒数据文件和异常文件指定一个不同的路径和文件。为此,请分别使用 COPY 选项 REJECTED DATA 和 EXCEPTIONS。您还可以将加载拒绝和异常情况保存在表中。有关详细信息,请参阅数据加载。
基本 Flex 表加载和查询
将数据加载到 Flex 表中与将数据加载到常规列式表中类似。差别在于,您必须在使用其中一种 Flex 解析器的同时使用 PARSER 选项:
=> COPY darkdata FROM '/home/dbadmin/data/tweets_12.json' PARSER fjsonparser();
Rows Loaded
-------------
12
(1 row)
注意
您可以在需要时使用许多额外的 COPY 参数,但并非所有这些参数都受到支持。将数据加载到 Flex 表的实际列
如果您创建具有一个或多个实际列定义的混合 Flex 表,则 COPY 在数据加载期间评估每个虚拟列键名,并使用来自对应虚拟列的值自动填充实际列。对于标量类型的列,COPY 还将键和值作为 VMap 数据的一部分加载到 __raw__
列。对于复杂类型的列,COPY 不会将值添加到 __raw__
列。
注意
随着时间的推移,在两种类型的列存储值可能会影响您的许可数据限制。有关 Vertica 许可证的详细信息,请参阅管理许可证。例如,继续使用 JSON 示例:
-
创建 Flex 表,该表具有待加载数据中一个键的列定义:
=> CREATE FLEX TABLE darkdata1 ("user.lang" VARCHAR); CREATE TABLE
-
将数据加载到表中:
=> COPY darkdata1 FROM '/test/vertica/flextable/DATA/tweets_12.json' PARSER fjsonparser(); Rows Loaded ------------- 12 (1 row)
-
直接查询实际列:
=> SELECT "user.lang" FROM darkdata1; user.lang ----------- es es tr it en en en en (12 rows)
实体化列中的空行指示 NULL 值。有关如何在 Flex 表中处理 NULL 值的详细信息,请参阅 NULL 值。
-
您可以查询其他具有类似结果的虚拟列:
=> SELECT "user.name" FROM darkdata1; user.name --------------------- I'm Toaster⥠Flu Beach seydo shi The End Uptown gentleman. ~G A B R I E L A ⿠Frederick Danjou laughing at clouds. (12 rows)
注意
虽然这两个查询的结果相似,但在访问键和键值方面,差异非常显著。user.lang
的数据已实体化为实际表列,而user.name
仍为虚拟列。对于生产级的数据使用(而非测试数据集),实体化 Flex 表数据可显著提高查询性能。
在加载过程中处理默认值
您可以创建具有一个实际列的 Flex 表,该实际列以传入数据中存在的一个虚拟列命名。例如,如果您加载的数据包含一个 user.lang
虚拟列,请用该列定义 Flex 表。您还可以在创建具有实际列的 Flex 表时,指定默认列值。下个示例演示了如何定义具有来自虚拟列 (user.name
) 的默认值的实际列 (user.lang
):
=> CREATE FLEX TABLE darkdata1 ("user.lang" LONG VARCHAR default "user.name");
将数据加载到 Flex 表中时,COPY 使用 Flex 表数据中的值,忽略默认列定义。要将数据加载到 Flex 表中,需要通过 MAPLOOKUP 找到与任何实际列名称相匹配的键。如果传入数据中具有名称与某个实际列相同的虚拟列,则存在匹配项。当 COPY 检测到匹配项时,它将用值填充该列。COPY 针对各行返回值或 NULL,因此实际列始终具有值。
例如,如前面的示例所述创建 Flex 表后,使用 COPY 加载数据:
=> COPY darkdata1 FROM '/test/vertica/flextable/DATA/tweets_12.json' PARSER fjsonparser();
Rows Loaded
-------------
12
(1 row)
如果您在加载后查询表,数据显示已提取 user.lang
列的值:
-
来自正在加载的数据 —
user.lang
虚拟列的值 -
带 NULL — 没有值的行
在这种情况下,user.lang
的表列默认值被忽略:
=> SELECT "user.lang" FROM darkdata1;
user.lang
-----------
it
en
es
en
en
es
tr
en
(12 rows)
使用 COPY 指定默认列值
您可以将表达式添加到 COPY 语句,以便在加载数据时指定默认列值。对于 Flex 表,如要指定任何列信息,您需要显示列出 __raw__
列。以下示例演示了如何使用默认列值的表达式。在这种情况下,加载数据即可用输入数据 user.name
的值填充已定义的 user.lang
列:
=> COPY darkdata1(__raw__, "user.lang" as "user.name"::VARCHAR)
FROM '/test/vertica/flextable/DATA/tweets_12.json' PARSER fjsonparser();
Rows Loaded
-------------
12
(1 row)
=> SELECT "user.lang" FROM darkdata1;
user.lang
---------------------
laughing at clouds.
Avita Desai
I'm Toasterâ¥
Uptown gentleman.
~G A B R I E L A â¿
Flu Beach
seydo shi
The End
(12 rows)
您可以按照更改 Flex 表中的说明,在添加列时指定默认值。执行此操作将导致不同的行为。有关使用 COPY、其表达式和参数的详细信息,请参阅数据加载和 COPY 参考页面。