许多客户端应用程序的主要任务是将数据加载到 Vertica 数据库。有多种不同方法可用于通过 ODBC 插入数据,本节中的主题介绍这些方法。
加载数据
- 1: 使用单行插入
- 2: 使用预定义的语句
- 3: 使用批量插入
- 3.1: 跟踪加载状态 (ODBC)
- 3.2: 批量加载过程中的错误处理
- 4: 使用 COPY 语句
- 5: 使用 COPY LOCAL 从客户端进行流式数据传输
1 - 使用单行插入
将数据加载到 Vertica 的最简单方法是使用 SQLExecuteDirect 函数运行 INSERT SQL 语句。但此方法仅能插入单个数据行。
2 - 使用预定义的语句
Vertica 支持将服务器端预定义的语句与 ODBC 和 JDBC 结合使用。使用预定义的语句,您只需定义一个语句一次,然后可以使用不同的参数多次运行该语句。要执行的语句包含占位符而非参数。执行语句时,应为每个占位符提供值。
在以下示例查询中,占位符用问号 (?) 表示:
SELECT * FROM public.inventory_fact WHERE product_key = ?
服务器端预定义的语句用于以下用途:
-
优化查询。Vertica 只需要解析语句一次。
-
防止 SQL 注入攻击。如果过滤用户输入时未能正确过滤嵌入在 SQL 语句中的字符串字面量转义字符,或者如果用户输入由于未强类型化而意外运行,则将发生 SQL 注入攻击。由于预定义的语句与输入数据分开进行解析,因此数据库不可能意外执行数据。
-
将直接变量绑定到返回列。通过指向数据结构,代码不必执行额外转换。
以下示例演示了使用预定义的语句执行单一插入。
3 - 使用批量插入
可以使用批量插入将数据区块插入到数据库中。通过将数据拆分为多个批,您可以在加载每个批后收到有关任何拒绝的行的信息,从而监控加载进度。若要通过 ODBC 执行批量加载,通常可以将预定义的语句与绑定到数组(包含要加载的数据)结合使用。对于每个批,应将新的数据集加载到数组中,然后执行预定义的语句。
执行批量加载时,Vertica 使用 COPY 语句加载数据。所加载的其他每个批使用同一个 COPY 语句。该语句将保持打开,直至您执行以下操作为止:结束语句,关闭语句的光标或执行非 INSERT 语句。
将单个 COPY 语句用于多个批可以通过以下途径提高批量加载效率:
-
减少插入各个批的开销
-
将各个批合并为较大的 ROS 容器
注意
如果数据库连接已启用 AUTOCOMMIT,则事务会在执行每个批量插入语句之后自动提交,从而关闭 COPY 语句。保持启用 AUTOCOMMIT 会降低批量加载的效率,并且会增加数据库中的开销,因为所有较小的加载会合并到一起。虽然 Vertica 使用单个 COPY 语句插入一个事务中的多个批,但您可以在加载每个批之后查找由于行格式无效或存在数据类型问题而被拒绝的行(如果有)。有关详细信息,请参阅跟踪加载状态 (ODBC)。
注意
虽然您可以在批量加载事务期间查找拒绝的行,但只会在 COPY 语句结束后报告其他类型的错误(例如,磁盘空间不足或节点关闭,此类错误会导致数据库不安全)。由于批量加载共享一个 COPY 语句,因此一个批中的错误会导致回退同一个事务中较早的批。
批量插入步骤
应用程序执行 ODBC 批量插入所需完成的步骤如下:
-
连接到数据库。
-
禁用连接的自动提交。
-
创建可插入要加载的数据的预定义的语句。
-
将该预定义的语句的参数绑定到包含要加载的数据的数组。
-
使用各个批的数据填充数组。
-
执行该预定义的语句。
-
(可选)检查批量加载的结果,以查找拒绝的行。
-
重复以上三个步骤,直至已加载所有要加载的数据为止。
-
提交事务。
-
(可选)检查整个批处理事务的结果。
以下示例代码演示了以上步骤的简化版本。
运行以上代码后的结果如下所示。
Allocated an environment handle.
Set application to ODBC 3.
Allocated Database handle.
Connecting to database.
Connected to database.
Creating prepared statement
Created prepared statement.
Bound CustIDs array to prepared statement
Bound CustNames array to prepared statement
Bound phoneNums array to prepared statement
Adding Batch #1...successful.
Adding Batch #2...successful.
Adding Batch #3...successful.
Adding Batch #4...successful.
Adding Batch #5...successful.
Committing transaction
Committed transaction
Free handles.
结果表如下所示:
=> SELECT * FROM customers;
CustID | CustName | Phone_Number
--------+-------------+-----------------
100 | Allen, Anna | 1-617-555-1234
101 | Brown, Bill | 1-781-555-1212
102 | Chu, Cindy | 1-508-555-4321
103 | Dodd, Don | 1-617-555-4444
100 | Allen, Anna | 1-617-555-1234
101 | Brown, Bill | 1-781-555-1212
102 | Chu, Cindy | 1-508-555-4321
103 | Dodd, Don | 1-617-555-4444
100 | Allen, Anna | 1-617-555-1234
101 | Brown, Bill | 1-781-555-1212
102 | Chu, Cindy | 1-508-555-4321
103 | Dodd, Don | 1-617-555-4444
100 | Allen, Anna | 1-617-555-1234
101 | Brown, Bill | 1-781-555-1212
102 | Chu, Cindy | 1-508-555-4321
103 | Dodd, Don | 1-617-555-4444
100 | Allen, Anna | 1-617-555-1234
101 | Brown, Bill | 1-781-555-1212
102 | Chu, Cindy | 1-508-555-4321
103 | Dodd, Don | 1-617-555-4444
(20 rows)
注意
与 SQL_C_NUMERIC 数据类型绑定的输入参数使用默认数值精度 (37) 和默认小数位数 (0),而不使用由 SQL_NUMERIC_STRUCT 输入值设置的精度和小数位数。此行为遵守 ODBC 标准。如果不想使用默认精度和小数位数,可以使用SQLSetDescField()
或 SQLSetDescRec()
在语句属性中更改精度和小数位数。
3.1 - 跟踪加载状态 (ODBC)
加载一批数据之后,客户端应用程序可以获取已处理的行数并确定每个是被接受还是被拒绝。
确定接受的行的数量
若要获取某个批所处理的行数,请将名为 SQL_ATTR_PARAMS_PROCESSED_PTR 且指向用于接收行数的变量的属性添加到语句对象中:
当应用程序调用 SQLExecute()
以插入该批时,Vertica ODBC 驱动程序会将已处理的行数(不一定等于已成功插入的行数)保存到您在 SQL_ATTR_PARAMS_PROCESSED_PTR 语句属性中指定的变量。
查找接受的行和拒绝的行
应用程序还可以设置名为 SQL_ATTR_PARAM_STATUS_PTR 且指向一个数组(ODBC 驱动程序可以将插入每个行的结果存储在此数组中)的语句属性:
该数组至少必须与每个批中要插入的行数一样大。
当应用程序调用 SQLExecute
以插入一个批时,ODBC 驱动程序会使用值填充该数组,这些值指示每个行已成功插入(SQL_PARAM_SUCCESS 或 SQL_PARAM_SUCCESS_WITH_INFO)还是遇到了错误 (SQL_PARAM_ERROR)。
以下示例扩展了使用批量插入中所示的示例,以便同时报告已处理的行数和插入的每个行的状态。
运行以上示例代码后,将生成以下输出:
Allocated an environment handle.Set application to ODBC 3.
Allocated Database handle.
Connecting to database.
Connected to database.
Creating table.
Created table.
Creating prepared statement
Created prepared statement.
Bound CustIDs array to prepared statement
Bound CustNames array to prepared statement
Bound phoneNums array to prepared statement
Adding Batch #1...Params processed: 4
Results of inserting each row:
Row 1 inserted successfully
Row 2 inserted successfully
Row 3 inserted successfully
Row 4 inserted successfully
Adding Batch #2...Params processed: 4
Results of inserting each row:
Row 1 inserted successfully
Row 2 inserted successfully
Row 3 inserted successfully
Row 4 inserted successfully
Adding Batch #3...Params processed: 4
Results of inserting each row:
Row 1 inserted successfully
Row 2 inserted successfully
Row 3 inserted successfully
Row 4 inserted successfully
Adding Batch #4...Params processed: 4
Results of inserting each row:
Row 1 inserted successfully
Row 2 inserted successfully
Row 3 inserted successfully
Row 4 inserted successfully
Adding Batch #5...Params processed: 4
Results of inserting each row:
Row 1 inserted successfully
Row 2 inserted successfully
Row 3 inserted successfully
Row 4 inserted successfully
Commit Transaction
Free handles.
3.2 - 批量加载过程中的错误处理
加载各个批时,您可以查找有关已接受的行数和已拒绝的行的信息(有关详细信息,请参阅跟踪加载状态 (ODBC))。插入各个批时,不会发生其他错误(例如磁盘空间错误)。此行为是由单个 COPY 语句对多个连续批执行加载导致的。使用单个 COPY 语句可使批量加载过程更快执行。只有 COPY 语句关闭时,才会提交批量数据,而且 Vertica 会报告其他类型错误。
批量加载应用程序应在 COPY 语句关闭时检查错误。一般情况下,可以通过调用 SQLEndTran()
函数以结束事务来强制 COPY 语句关闭。您还可以通过以下方法强制 COPY 语句关闭:使用 SQLCloseCursor()
函数关闭光标,或者在加载中插入最后一批之前将数据库连接的 AutoCommit 属性设置为 true。
注意
如果您执行任何非插入语句,COPY 语句也会关闭。但是,您可能无法凭直觉确定必须处理 COPY 语句(其中的查询可能不相关)中的错误,这样会造成混乱并导致更难以维护应用程序。您应当在批量加载结束时显式终止 COPY 语句,同时处理任何错误。4 - 使用 COPY 语句
COPY 允许您将存储在数据库节点上的文件中的数据批量加载到 Vertica 数据库。此方法是将数据加载到 Vertica 的最高效方法,因为文件驻留在数据库服务器上。您必须是超级用户才能使用 COPY 访问数据库节点的文件系统。
重要
在 Vertica ≤ 9.2 版本中创建的数据库中,COPY 支持 DIRECT 选项,该选项指定将数据直接加载到
ROS 而不是 WOS。将大型 (>100MB) 文件加载到数据库时使用此选项;否则,负载可能会填满 WOS。发生这种情况时, Tuple Mover 必须对 WOS 数据执行 移出 操作。直接加载到 ROS 更高效,并且可避免强制执行 moveout。
在 Vertica 9.3 中创建的数据库中,Vertica 忽略加载选项和提示,并始终使用 DIRECT 加载方法。≥ 10.0 版本创建的数据库不再支持 WOS 和移出操作;所有数据总是直接加载到 ROS 中。
注意
当在 COPY 命令中指定了例外和拒绝的数据修饰符时,将在客户端计算机上创建例外/拒绝文件。从驱动程序执行 COPY 查询时,请为这些修饰符指定本地路径和文件名。以下示例演示了如何使用 COPY 命令。
该示例在运行后输出了以下内容:
Allocated an environment handle.
Set application to ODBC 3.
Connecting to database.
Connected to database.
Disabling autocommit.
Successfully inserted 10001 rows.
Committing transaction
Committed transaction
Free handles.
5 - 使用 COPY LOCAL 从客户端进行流式数据传输
COPY LOCAL 将数据从客户端系统文件流式传输到 Vertica 数据库。此语句通过 ODBC 驱动程序进行工作,从而简化了将数据文件从客户端传输到服务器的任务。
COPY LOCAL 通过 ODBC 驱动程序以透明方式工作。当客户端应用程序执行 COPY LOCAL 语句时,ODBC 驱动程序将从客户端读取数据文件并将其流式传输到服务器。
注意
COPY LOCAL 必须是查询中的第一条语句,否则 Vertica 会返回错误。此示例演示如何使用 COPY LOCAL 语句从客户端系统加载数据:
除了使用 COPY 语句的 LOCAL 选项从客户端系统而非数据库节点的文件系统加载数据之外,此示例与使用 COPY 语句中所示的示例基本相同。