E.8. lt_bulkload(批量加载)

E.8.1. 概述
E.8.2. 描述
E.8.3. 用法
E.8.4. 选项
E.8.5. 控制文件
E.8.6. 限制
E.8.7. 详细信息

lt_bulkload(批量加载)是 LightDB 的高速数据加载工具。

lt_bulkload(批量加载)旨在将大量的数据加载到数据库中。 您可以通过绕过 LightDB 的共享缓冲区将数据加载到表中。

lt_bulkload(批量加载)还具有一些 ETL(Extract-Transform-Load)功能;输入数据验证和数据转换。

E.8.1. 概述

lt_bulkload(批量加载)[ OPTIONS ] [ controlfile(控制文件) ]

E.8.2. 描述

lt_bulkload(批量加载)旨在将大量的数据加载到数据库中。您可以选择是否检查数据库约束以及在加载过程中忽略多少个错误。 例如,当您从另一个数据库复制数据到 LightDB 时,可以跳过完整性检查以提高性能。另一方面,当加载不干净的数据时,可以启用约束检查。

lt_bulkload(批量加载)可以将加载数据转换为二进制文件,该文件可以用作 lt_bulkload 的输入文件。 如果在将加载数据转换为二进制文件时检查其是否有效,则可以在从二进制文件加载数据时跳过检查。

E.8.3. 用法

您可以通过以下三个步骤使用 lt_bulkload(批量加载):

1. 编辑控制文件 "sample_csv.ctl" 或 "sample_bin.ctl",其中包含数据加载的设置。 您可以指定表名、输入文件的绝对路径、输入文件的描述等。

2. 假设存在一个名为 $LTDATA/lt_bulkload 的目录,在其中创建加载状态文件。

3. 使用控制文件作为参数执行命令。该参数可使用相对路径。

            $ lt_bulkload sample_csv.ctl
            NOTICE: BULK LOAD START
            NOTICE: BULK LOAD END
            	0 Rows skipped.
            	8 Rows successfully loaded.
            	0 Rows not loaded due to parse errors.
            	0 Rows not loaded due to duplicate errors.
            	0 Rows replaced with new rows.
        

E.8.4. 选项

lt_bulkload(批量加载)具有以下命令行选项:

E.8.4.1. 加载选项

                -i INPUT
                --input=INPUT
                --infile=INPUT
                数据源路径。与控制文件中的 "INPUT" 相同。
                -O OUTPUT
                --output=OUTPUT
                数据存储路径。与控制文件中的 "OUTPUT" 相同。
                -l LOGFILE
                --logfile=LOGFILE
                写入结果日志的路径。与控制文件中的 "LOGFILE" 相同。
                -P PARSE_BADFILE
                --parse-badfile=PARSE_BADFILE
                写入无法正确解析的异常记录的路径。与控制文件中的 "PARSE_BADFILE" 相同。
                -u DUPLICATE_BADFILE
                --duplicate-badfile=DUPLICATE_BADFILE
                写入因在索引重建过程中与唯一约束冲突而被视为异常的记录的路径。与控制文件中的 "DUPLICATE_BADFILE" 相同。
                -o "key=val"
                --option="key=val"
                控制文件中可用的任何选项。可以传递多个选项。
            

E.8.4.2. 连接选项

连接服务器的选项。

                -d dbname
                --dbname dbname
                指定要连接的数据库的名称。如果未指定,则从环境变量 LTDATABASE 中读取数据库名称。如果未设置,则使用连接指定的用户名。
                -h host
                --host host
                指定运行服务器的计算机的主机名。如果值以斜杠开头,则将其用作 Unix 域套接字的目录。
                -p port
                --port port
                指定服务器用于侦听连接的 TCP 端口或本地 Unix 域套接字文件扩展名。
                -U username
                --username username
                要连接的用户名。
                -W
                --password
                强制 lt_bulkload 提示输入密码后再连接到数据库。
                该选项从不是必需的,因为如果服务器要求密码身份验证,lt_bulkload 会自动提示输入密码。但是,vacuumdb 将浪费一个连接尝试以找出服务器需要密码。在某些情况下,为了避免额外的连接尝试,输入 -W
                是值得的。
            

E.8.4.3. 常规选项

                -e
                --echo
                回显发送到服务器的命令。
                -E
                --elevel
                选择从 DEBUG、INFO、NOTICE、WARNING、ERROR、LOG、FATAL 和 PANIC 中输出的消息级别。默认为 INFO。
                --help
                显示程序的用法。
                --version
                显示程序的版本号。
            

E.8.5. 控制文件

您可以指定以下加载选项。控制文件可以使用绝对路径或相对路径指定。如果您使用相对路径指定它,则相对于执行 lt_bulkload 命令的当前工作目录。如果您没有指定控制文件,则应通过 lt_bulkload 的命令行参数传递所需的选项。

控制文件中可用以下参数。每行 "#" 后面的字符将被视为注释并被忽略。

E.8.5.1. 通用

TYPE = CSV | BINARY | FIXED | FUNCTION

输入数据的类型。默认为 CSV。

  • CSV:从 CSV 格式的文本文件加载。

  • BINARY | FIXED:从固定的二进制文件加载。

  • FUNCTION:从函数返回的结果集加载。

    如果使用,则 "INPUT" 必须是调用函数的表达式。

INPUT | INFILE = path | stdin | [ schemaname. ] function_name (argvalue, ...)

要加载数据的源。始终需要。根据 TYPE 选项,该值的处理方式如下:

  • 服务器上的文件:这是服务器中的文件路径。如果它是相对路径, 则在控制文件中指定时,它将相对于控制文件,或者在命令行参数中指定时, 它将相对于当前工作目录。LightDB 服务器的用户必须具有对该文件的读取权限。 仅在 "TYPE=CSV" 或 "TYPE=BINARY" 时可用。

  • lt_bulkload 命令的标准输入: "INPUT=stdin" 表示 lt_bulkload 将通过网络从 lt_bulkload 客户端程序的标准输入读取数据。 当输入文件和数据库位于不同的服务器上时,应使用此形式。仅在 "TYPE=CSV" 或 "TYPE=BINARY" 时可用。

  • SQL 函数:指定一个带有参数并返回输入数据集的 SQL 函数。仅在 "TYPE=FUNCTION" 时可用。 您不仅可以使用内置函数,还可以使用任何用户定义的函数。定义的函数应返回 SETOF sometype 类型或 RETURNS TABLE(columns) 类型。如果使用 sometype,则应指定属性类型。因为有一种情况,即 lt_bulkload 内部使用的赋值强制转换为 cstring 类型,不被允许。请注意,您可能需要使用 C 语言开发这些函数,而不是使用 PL/pgSQL,因为函数必须使用 SFRM_ValuePerCall 模式进行流式加载。

    下面是用户定义函数的示例。

                            $ CREATE TYPE sample_type AS (sum integer, name char(10));
                            $ CREATE FUNCTION sample_function() RETURNS SETOF sample_type
                                AS $$ SELECT id1 + id2, upper(name) FROM INPUT_TABLE $$
                                LANGUAGE SQL;
                        

    下面是控制文件的示例。

                            TABLE = sample_table
                            TYPE = FUNCTION
                            WRITER = DIRECT
                            INPUT = sample_function() # 如果使用自定义函数
                            #INPUT = generate_series(1, 1000) # 如果使用内置函数,它将生成从 1 到 1000 的顺序号
                        

WRITER | LOADER = DIRECT | BUFFERED | BINARY | PARALLEL

加载数据的方法。默认为 DIRECT。

  • DIRECT:直接将数据加载到表中。绕过共享缓冲区并跳过 WAL 记录,但需要自己的恢复过程。这是默认值,也是旧版本的模式。

  • BUFFERED:通过共享缓冲区将数据加载到表中。使用共享缓冲区,写入 WAL,并使用原始的 LightDB WAL 恢复。

  • BINARY:将数据转换为二进制文件,该文件可用作输入文件以加载。创建加载输出二进制文件所需的控制文件示例。此示例文件将在与二进制文件相同的目录中创建。

  • PARALLEL:与 "WRITER=DIRECT" 和 "MULTI_PROCESS=YES" 相同。如果指定了 PARALLEL,则忽略 MULTI_PROCESS。如果配置了密码身份验证以加载数据库,则必须设置密码文件。有关详细信息,请参见限制。

OUTPUT | TABLE = { [ schema_name. ] table_name | outfile }

要加载数据的目标。始终需要。根据 WRITER (或 LOADER) 选项,该值的处理方式如下:

  • 要加载到的表:指定要加载到的表。如果省略了 schema_name,则使用搜索路径中的第一个匹配表。仅当 WRITER 为 DIRECT、BUFFERED 或 PARALLEL 时,才能将数据加载到表中。

  • 服务器上的文件:指定服务器上输出文件的路径。如果是相对路径,则将以与 INPUT 选项相同的方式解释它。运行 LightDB 的 OS 用户必须对指定文件的父目录具有写权限。仅当 WRITER 为 BINARY 时,才能将数据加载(转换)到文件中。

SKIP | OFFSET = n

要跳过的输入行数。默认为 0。您不能同时指定 "TYPE=FUNCTION" 和 SKIP。

LIMIT | LOAD = n

要加载的行数。默认为 INFINITE,即所有数据都将加载。即使使用 TYPE=FUNCTION,也可以使用此选项。

ENCODING = encoding

指定输入数据的编码。检查指定的编码是否有效,并根据需要将输入数据转换为数据库编码。 默认情况下,不验证输入数据的编码,也不进行转换。如果您可以确保输入数据以数据库编码进行编码, 则可以通过不指定此选项并跳过编码验证和转换来减少加载时间。请注意,仅当 INPUT 为 stdin 时, 默认情况下才使用 client_encoding 作为输入数据的编码。您不能同时指定 "TYPE=FUNCTION" 和 ENCODING。

下面是选项值和实际行为:

                                                            DB encoding
                                                                    SQL_ASCII	                        non-SQL_ASCII
                    not specified	                    neither checked nor converted	    neither checked nor converted
                    SQL_ASCII	                            neither checked nor converted	    only checked
                    non-SQL_ASCII,                          same as DB	only checked	            only checked
                    non-SQL_ASCII, different from DB	    only checked	                    checked and converted
                

FILTER = [ schema_name. ] function_name [ (argtype, ... ) ]

指定过滤函数以转换输入文件中的每一行。只要函数名在数据库中是唯一的,就可以省略 argtype 的定义。 如果未指定,则输入数据将直接解析为加载目标表。另请参阅如何编写过滤器函数以创建过滤器函数。

您不能同时指定 "TYPE=FUNCTION" 和 FILTER。另外,在 CSV 选项中的 FORCE_NOT_NULL 不能与 FILTER 选项一起使用。

CHECK_CONSTRAINTS = YES | NO

指定在加载过程中是否检查 CHECK 约束。默认为 NO。您不能同时指定 "WRITER=BINARY" 和 CHECK_CONSTRAINTS。

PARSE_ERRORS = n

在解析、编码检查、编码转换、FILTER 函数、CHECK 约束检查、NOT NULL 检查或数据类型转换期间引发错误的被忽略的元组数。 无效的输入元组不会被加载,并记录在 PARSE BADFILE 中。默认值为 0。如果有相等或更多的解析错误, 则已加载的数据将被提交,而其余的元组将不会被加载。0 表示不允许出现错误,-1 和 INFINITE 表示忽略所有错误。

DUPLICATE_ERRORS = n

违反唯一约束的被忽略的元组数。冲突的元组将从表中删除,并记录在 DUPLICATE BADFILE 中。默认值为 0。 如果有相等或更多的唯一违规行为,则整个加载将被回滚。0 表示不允许任何违规行为,-1 和 INFINITE 表示忽略所有违规行为。 您不能同时指定 "WRITER=BINARY" 和 DUPLICATE_ERRORS。

ON_DUPLICATE_KEEP = NEW | OLD

指定如何处理违反唯一约束的元组。删除的元组将记录在 BAD 文件中。默认为 NEW。如果启用此选项,还需要将 DUPLICATE_ERRORS 设置为大于 0。 您不能同时指定 "WRITER=BINARY" 和 ON_DUPLICATE_KEEP。

  • NEW:保留输入数据中的元组,并删除相应的现有元组。当数据中都有违反的元组时,保留后者。

  • OLD:保留现有元组并删除输入数据中的元组。

LOGFILE = path

写入结果日志的路径。如果指定了相对路径,则将其视为与 INPUT 相同。默认为 $LTDATA/lt_bulkload/timestamp_dbname_schema_table.log。

PARSE_BADFILE = 路径

BAD文件的路径,用于记录在解析、编码检查、编码转换、FILTER函数、CHECK约束检查、NOT NULL检查或数据类型转换过程中出现错误的无效记录。 文件格式与输入源文件相同。如果指定相对路径,则被视为与输入文件相同。 默认路径为 $LTDATA/lt_bulkload/timestamp_dbname_schema_table.bad.extension-of-infile。

DUPLICATE_BADFILE = 路径

用于在索引重建期间记录与唯一约束冲突的错误记录的文件路径。文件格式始终为CSV。如果指定相对路径,则被视为与输入文件相同。 默认路径为 $LTDATA/lt_bulkload/timestamp_dbname_schema_table.dup.csv。不应同时指定"WRITER=BINARY"和DUPLICATE_BADFILE。

TRUNCATE = YES | NO

如果为YES,则使用TRUNCATE命令从目标表中删除所有行。如果为NO,则不执行任何操作。默认值为NO。 不应同时指定"WRITER=BINARY"和TRUNCATE。

VERBOSE = YES | NO

如果为YES,则在服务器日志中记录错误的元组。如果为NO,则不在服务器日志中记录。默认为NO。

MULTI_PROCESS = YES | NO

如果为YES,则使用多个线程并行进行数据读取、解析和写入。如果为NO,则仅使用单个线程处理它们,而不进行并行处理。 默认为NO。如果WRITER为PARALLEL,则忽略MULTI_PROCESS。如果为加载数据库配置了密码身份验证,则必须设置密码文件。有关详细信息,请参见限制。 启用MULTI_PROCESS时,请确保没有其他LightDB后端进程尝试修改表的模式,因为这可能导致读取和写入进程所看到的表模式不同并导致问题。

E.8.5.2. CSV输入格式

DELIMITER = 分隔符字符

文件中每行内(行)分隔列的单个ASCII字符。默认为逗号。当您加载一个以制表符分隔的格式文件(TSV)时,可以将DELIMITER设置为制表符字符。 然后,您需要将制表符用双引号括起来:

                DELIMITER=" " # 一个双引号括起来的制表符
            

您还可以使用$'\t'语法将DELIMITER指定为命令行-o选项。

                $ lt_bulkload tsv.ctl -o $'DELIMITER=\t'
            

QUOTE = 引号字符

指定ASCII引号字符。默认为双引号。

ESCAPE = 转义字符

指定应出现在引号数据字符值之前的ASCII字符。默认为双引号。

NULL = 空字符串

表示空值的字符串。默认为没有引号的空值。

FORCE_NOT_NULL = 列名

将每个指定的列视为非NULL值进行处理。可以根据需要使用多个列。不能与FILTER选项一起使用。

E.8.5.3. 二进制输入格式

COL = 类型 [ (大小) ] [ NULLIF { '空字符串' | 空值十六进制 } ]

从左到右的输入文件的列定义。定义包括类型名称、偏移量和字节长度。CHAR和VARCHAR表示输入数据是文本。否则,它是二进制数据。 如果是二进制的,则必须在服务器和数据文件之间匹配字节序。

  • CHAR | CHARACTER:一个去除尾部空格的字符串。长度始终是必需的。

  • VARCHAR | CHARACTER VARYING:一个保留尾部空格的字符串。长度始终是必需的。

  • SMALLINT | SHOFT:2字节的带符号整数。

  • INTEGER | INT:2、4或8字节的带符号整数。默认值为4。

  • BIGINT | LONG:8字节的带符号整数。

  • UNSIGNED SMALLINT | SHORT:2字节的无符号整数。

  • UNSIGNED INTEGER | INT:2或4字节的无符号整数。默认值为4。

  • FLOAT | REAL:4或8字节的浮点数。默认值为4。

  • DOUBLE:8字节的浮点数。

可以如下指定类型的长度和偏移量:

  • TYPE:带有默认长度的TYPE。

  • TYPE(L):长度为L字节的TYPE。

  • TYPE(S+L):长度为L字节,偏移量为S字节,从行的开头计算。

  • TYPE(S:E):从S字节开始,到E字节结束。

可以如下指定类型的长度和偏移量:

  • NULLIF '空字符串':当类型为CHAR或VARCHAR时,指定表示NULL的字符串。字符串的长度必须与类型的长度相同。

  • NULLIF 空值十六进制:当类型不是CHAR和VARCHAR时,指定表示NULL的十六进制值。十六进制值的长度必须与类型的长度相同。

另外,"COL N"也可用,与COL CHAR(N)相同,用于向后兼容性。

PRESERVE_BLANKS = YES | NO

YES将"COL N"视为"COL CHAR(N)",而NO将其视为"COL VARCHAR(N)"。默认为NO。

STRIDE = n

一行的长度。如果要截断行的末尾,请使用它。默认为整行,即所有COL的总和。

E.8.5.4. 二进制输出格式

OUT_COL = 类型 [ (大小) ] [ NULLIF { '空字符串' | 空值十六进制 } ]

从左到右的输出文件的列定义。定义包括类型名称、偏移量和字节长度。CHAR和VARCHAR表示输入数据是文本。否则,它是二进制数据。 如果是二进制的,则必须在服务器和数据文件之间匹配字节序。

  • CHAR | CHARACTER:固定长度的字符串。必须指定长度。如果要存储的字符串比声明的长度短,则值将填充空格。 "COL=CHAR(size)"将在控制文件的示例中输出。

  • VARCHAR | CHARACTER VARYING:固定长度的字符串。必须指定长度。如果要存储的字符串比声明的长度短,则值将填充空格。 "COL=VARCHAR(size)"将在控制文件的示例中输出。

  • SMALLINT | SHOFT:2字节的带符号整数。

  • INTEGER | INT:2、4或8字节的带符号整数。默认值为4。

  • BIGINT | LONG:8字节的带符号整数。

  • UNSIGNED SMALLINT | SHORT:2字节的无符号整数。

  • UNSIGNED INTEGER | INT:2或4字节的无符号整数。默认值为4。

  • FLOAT | REAL:4或8字节的浮点数。默认值为4。

  • DOUBLE:8字节的浮点数。

可以如下指定表示NULL的字符串。如果省略但输入为NULL,则在PARSE_BADFILE中将NULL记录为无效数据。

  • NULLIF '空字符串':当类型为CHAR或VARCHAR时,指定表示NULL的字符串。字符串的长度必须与类型的长度相同。

  • NULLIF 空值十六进制:当类型不是CHAR和VARCHAR时,指定表示NULL的十六进制值。十六进制值的长度必须与类型的长度相同。

E.8.6. 限制

E.8.6.1. lt_bulkload的退出代码

当成功加载时,lt_bulkload返回0。即使加载本身已完成,但存在一些解析错误或重复错误时,它还会返回带有“警告”消息的3。 请注意,跳过的行和替换的行(使用ON_DUPLICATE_KEEP = NEW)不被视为错误;退出代码将为0。

当存在不可继续的错误时,加载程序会引发一个“错误”消息。返回代码通常为1,因为在加载数据期间,数据库服务器会发生许多错误。 以下表格显示了lt_bulkload可以返回的代码。

                Return code	                        Description
                    0	            Success
                    1	            Error occurred during running SQL in LightDB
                    2	            Failed to connect to LightDB
                    3	            Success, but some data could not be loaded
            

E.8.6.2. 关于直接加载

如果使用直接加载模式(WRITER=DIRECT或PARALLEL),则必须注意以下事项:

E.8.6.2.1. LightDB启动顺序

当lt_bulkload崩溃并且在$LTDATA/lt_bulkload中保留了一些.loadstatus文件时, 必须使用“lt_bulkload -r”命令进行lt_bulkload自身的恢复,然后再调用lt_ctl start。 您必须使用LightDB脚本启动和停止LightDB,该脚本会正确地调用“lt_bulkload -r”和“lt_ctl start”。 我们建议不要直接使用lt_ctl。

E.8.6.2.2. PITR/复制

由于绕过了WAL,因此PITR的存档恢复不可用。这并不意味着可以在没有加载表数据的情况下进行PITR。 如果要使用PITR,请在通过lt_bulkload加载后对数据库进行完全备份。如果使用流式复制, 则需要基于在lt_bulkload之后进行备份的备份集重新创建备用站。

E.8.6.2.3. $LTDATA/lt_bulkload中的加载状态文件

您不能删除$LTDATA/lt_bulkload目录中找到的加载状态文件(*.loadstatus)。这个文件在lt_bulkload崩溃恢复中是必需的。

E.8.6.2.4. 不要使用kill -9

尽可能不要使用“kill -9”终止lt_bulkload命令。如果您这样做了, 您必须调用LightDB脚本执行lt_bulkload恢复并重新启动LightDB以继续。

E.8.6.2.5. 当MULTI_PROCESS=YES时,身份验证可能会失败

当MULTI_PROCESS=YES且需要从localhost连接到数据库以加载时,即使在提示符中正确输入密码,身份验证也会失败。 要避免这种情况,请配置以下任一项。

  • 使用“信任”方法对来自localhost的连接进行身份验证

    在UNIX环境中,来自localhost的连接使用UNIX域套接字。 在UNIX中,将以下行添加到lt_hba.conf中。

                                # TYPE  DATABASE        USER            CIDR-ADDRESS            METHOD [for UNIX]
                                local   all             foo                                     trust
                            
  • 在.pgpass文件中指定密码

    如果出于安全原因不想使用“trust”方法,请使用“md5”或“password”作为身份验证方法,并在.pgpass文件中指定密码。 请注意,.pgpass文件必须位于运行LightDB服务器的操作系统用户(通常为“LightDB”用户)的主目录中。 例如,如果lt_bulkload连接到以DB用户“foo”为身份,其密码为“foopass”的端口5432上运行的服务器, 管理员可以将以下行添加到.pgpass文件中:

                                localhost:5432:*:foo:foopass
                            
  • 在.pgpass文件中指定密码

    不要使用“WRITER=PARALLEL”

                                使用除“WRITER=PARALLEL”之外的加载方法。
                            

E.8.6.3. 数据库约束

在默认情况下,仅强制执行唯一约束和非空约束以进行数据加载。 您可以设置“CHECK_CONSTRAINTS=YES”以检查CHECK约束。无法检查外键约束。 用户有责任提供有效的数据集。

E.8.7. 详细信息

E.8.7.1. 如何编写FILTER函数

当您编写FILTER函数时,有一些注意事项和警告:

  • 输入文件中的记录逐个传递给FILTER函数。

  • 当FILTER函数发生错误时,传递的记录不会加载并写入PARSE BADFILE。

  • FILTER函数必须返回记录类型或一些复合类型。此外,实际记录类型必须与目标表定义匹配。

  • 如果FILTER函数返回NULL,则加载具有所有列中NULL的记录。

  • 支持具有默认参数的函数。如果输入数据的列数少于函数的参数数,则将使用默认值。

  • 不支持VARIADIC函数。

  • SETOF函数不受支持。

  • 不支持具有通用类型(任何,任何元素等)的函数。

  • FILTER函数可以使用任何语言实现。 SQL,C,PL等都可以, 但是应尽可能快地编写函数,因为它们被调用的次数很多。

  • 您只能指定FILTER或FORCE_NOT_NULL选项之一。如果需要此功能,请重新实现与FORCE_NOT_NULL兼容的FILTER函数。

这是一个FILTER函数的示例。

                CREATE FUNCTION sample_filter(integer, text, text, real DEFAULT 0.05) RETURNS record
                    AS $$ SELECT $1 * $4, upper($3) $$
                    LANGUAGE SQL;