Appender 可用于将批量数据加载到 DuckDB 数据库中。目前可在 C、C++、Go、Java 和 Rust API 中使用。Appender 与连接绑定,并在追加时使用该连接的事务上下文。Appender 总是追加到数据库文件中的单个表。
在C++ API中,Appender的工作方式如下:
DuckDB db;
Connection con(db);
// create the table
con.Query("CREATE TABLE people (id INTEGER, name VARCHAR)");
// initialize the appender
Appender appender(con, "people");
AppendRow
函数是追加数据的最简单方法。它使用递归模板,允许您在一个函数调用中放置单行的所有值,如下所示:
appender.AppendRow(1, "Mark");
行也可以使用BeginRow
、EndRow
和Append
方法单独构建。这是由AppendRow
在内部完成的,因此具有相同的性能特征。
appender.BeginRow();
appender.Append<int32_t>(2);
appender.Append<string>("Hannes");
appender.EndRow();
出于性能考虑,添加到Appender的任何值在插入数据库系统之前都会被缓存。这意味着,在追加时,这些行可能不会立即在系统中可见。当Appender超出范围或调用appender.Close()
时,缓存会自动刷新。也可以使用appender.Flush()
方法手动刷新缓存。在调用Flush
或Close
之后,所有数据都已写入数据库系统。
日期、时间和时间戳
虽然数字和字符串相当直观,但日期、时间和时间戳需要一些解释。它们可以直接使用duckdb::Date
、duckdb::Time
或duckdb::Timestamp
提供的方法附加。它们也可以使用内部的duckdb::Value
类型附加,然而,这会增加一些额外的开销,应尽可能避免。
以下是一个简短的示例:
con.Query("CREATE TABLE dates (d DATE, t TIME, ts TIMESTAMP)");
Appender appender(con, "dates");
// construct the values using the Date/Time/Timestamp types
// (this is the most efficient approach)
appender.AppendRow(
Date::FromDate(1992, 1, 1),
Time::FromTime(1, 1, 1, 0),
Timestamp::FromDatetime(Date::FromDate(1992, 1, 1), Time::FromTime(1, 1, 1, 0))
);
// construct duckdb::Value objects
appender.AppendRow(
Value::DATE(1992, 1, 1),
Value::TIME(1, 1, 1, 0),
Value::TIMESTAMP(1992, 1, 1, 1, 1, 1, 0)
);
提交频率
默认情况下,追加器每204,800行执行一次提交。
您可以通过显式使用事务并围绕您的AppendRow
调用批次使用BEGIN TRANSACTION
和COMMIT
语句来更改此设置。
处理约束违规
如果Appender遇到PRIMARY KEY
冲突或UNIQUE
约束冲突,它将失败并返回以下错误:
Constraint Error: PRIMARY KEY or UNIQUE constraint violated: duplicate key "..."
在这种情况下,整个追加操作失败,没有插入任何行。
其他客户端中的Appender支持
Appender 也可在以下客户端 API 中使用: