Appender(批量追加器)
Appender 可用于将批量数据加载到 Goose 数据库中。它目前在 C、C++、Go、Java 和 Rust API 中可用。Appender 与某个连接绑定,执行追加时会使用该连接的事务上下文。一个 Appender 始终只会向数据库文件中的一张表追加数据。
在 C++ API 中,Appender 的使用方式如下:
Goose 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() 时,缓存会自动刷新(flush)。你也可以调用 appender.Flush() 手动刷新缓存。无论调用 Flush 还是 Close,都会将所有数据写入数据库系统。
日期、时间与时间戳
数字与字符串比较直观,但日期、时间和时间戳需要额外说明。它们可以通过 goose::Date、goose::Time 或 goose::Timestamp 提供的方法直接追加。你也可以使用内部的 goose::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 goose::Value objects
appender.AppendRow(
Value::DATE(1992, 1, 1),
Value::TIME(1, 1, 1, 0),
Value::TIMESTAMP(1992, 1, 1, 1, 1, 1, 0)
);
提交频率
默认情况下,Appender 每追加 204,800 行就会执行一次提交(commit)。
你可以通过显式使用事务来改变这一行为:用 BEGIN TRANSACTION 与 COMMIT 语句把一批 AppendRow 调用包起来。
处理约束冲突
如果 Appender 遇到 PRIMARY KEY 冲突或违反 UNIQUE 约束,它会失败并返回如下错误:
Constraint Error:
PRIMARY KEY or UNIQUE constraint violated: duplicate key "..."
在这种情况下,整个追加操作会失败,且不会插入任何行。
其他客户端中的 Appender 支持
Appender 在以下客户端 API 中也可用: