You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用SOCI对std::vector自定义对象执行批量插入?

使用SOCI实现自定义对象vector的批量插入

方法1:利用SOCI原生批量绑定API(推荐)

SOCI内置了批量操作支持,核心是通过statement对象绑定批量数据的连续内存,底层会根据数据库驱动自动选择最优的批量插入方式(如MySQL的多行插入、PostgreSQL的COPY),性能远高于循环单条插入。

假设你的one_min_equity结构体及类型转换已完成,示例代码如下:

#include <soci/soci.h>
#include <vector>
#include <string>
#include <tm.h>

namespace models {
struct one_min_equity {
    std::string symbol;
    std::tm trade_time;
    double open_price;
    double close_price;
    // 其他字段...
};
}

// 已实现的type_conversion模板(示例框架)
namespace soci {
template<>
struct type_conversion<models::one_min_equity> {
    typedef values base_type;

    static void from_base(values const& v, indicator ind, models::one_min_equity& e) {
        // 字段读取逻辑
        e.symbol = v.get<std::string>("symbol");
        e.trade_time = v.get<std::tm>("trade_time");
        // ...其他字段
    }

    static void to_base(models::one_min_equity const& e, values& v, indicator& ind) {
        // 字段写入逻辑
        v.set("symbol", e.symbol);
        v.set("trade_time", e.trade_time);
        // ...其他字段
        ind = i_ok;
    }
};
}

void bulk_insert_equity(soci::session& sql, const std::vector<models::one_min_equity>& rows) {
    if (rows.empty()) return;

    // 提取每个字段的批量数据(也可手动构造vector)
    std::vector<std::string> symbols;
    std::vector<std::tm> trade_times;
    std::vector<double> open_prices;
    std::vector<double> close_prices;

    symbols.reserve(rows.size());
    trade_times.reserve(rows.size());
    open_prices.reserve(rows.size());
    close_prices.reserve(rows.size());

    for (const auto& row : rows) {
        symbols.push_back(row.symbol);
        trade_times.push_back(row.trade_time);
        open_prices.push_back(row.open_price);
        close_prices.push_back(row.close_price);
    }

    // 准备批量插入语句,绑定批量字段
    soci::statement st = sql.prepare <<
        "INSERT INTO one_min_equity (symbol, trade_time, open_price, close_price) "
        "VALUES (:sym, :time, :open, :close)",
        soci::use(symbols, "sym"),
        soci::use(trade_times, "time"),
        soci::use(open_prices, "open"),
        soci::use(close_prices, "close");

    // 执行批量插入,true开启批量模式
    st.execute(true);
}

说明

  • soci::use接收vector时会自动识别为批量数据,驱动会根据数据库特性优化插入逻辑。
  • execute(true)触发批量执行,SOCI会自动处理数据提交的批次大小,平衡性能与内存占用。

方法2:构造多行VALUES语句(适合简单场景)

如果数据库支持多行INSERT语法(如INSERT INTO table (col1,col2) VALUES (v1,v2),(v3,v4)...),可手动构造SQL语句一次性执行,适合数据量不大的场景。

示例代码:

void bulk_insert_equity(soci::session& sql, const std::vector<models::one_min_equity>& rows) {
    if (rows.empty()) return;

    const size_t batch_size = 1000; // 分批次避免SQL过长
    for (size_t start = 0; start < rows.size(); start += batch_size) {
        size_t end = std::min(start + batch_size, rows.size());
        std::ostringstream oss;
        oss << "INSERT INTO one_min_equity (symbol, trade_time, open_price, close_price) VALUES ";

        // 构造VALUES片段
        for (size_t i = start; i < end; ++i) {
            if (i > start) oss << ", ";
            oss << "(:sym" << i << ", :time" << i << ", :open" << i << ", :close" << i << ")";
        }

        soci::statement st = sql.prepare << oss.str();

        // 绑定当前批次的所有字段
        for (size_t i = start; i < end; ++i) {
            st.exchange(soci::use(rows[i].symbol, "sym" + std::to_string(i)));
            st.exchange(soci::use(rows[i].trade_time, "time" + std::to_string(i)));
            st.exchange(soci::use(rows[i].open_price, "open" + std::to_string(i)));
            st.exchange(soci::use(rows[i].close_price, "close" + std::to_string(i)));
        }

        st.execute();
    }
}

注意

  • 需按批次拆分数据,避免触发数据库的SQL长度限制。
  • 性能略逊于原生批量绑定,适合快速实现小批量插入。

关键提示

  • 确保自定义类型的type_conversion模板逻辑正确,批量操作依赖单个对象的字段映射规则。
  • 不同数据库驱动对批量操作的优化不同,优先使用方法1的原生批量绑定以获得最佳性能。

内容的提问来源于stack exchange,提问作者srilakshmikanthanp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 09:03:09