1

我有一个将数据读入地图并将它们写入 sqlite 数据库的应用程序。该应用程序做了很多其他事情,并且是异步的(使用 boost asio),除了写入 db 部分。这是示例伪代码:

struct records;
std::map<int, records> list;
void read() {
    // Dump(read) X records into list
    // If record id doesn't exist, add it. dirty = true
    // If it exists, update all other fields. dirty = true if any fields changed.
}

void writeDB() {
    sqlite3_prepare_v2();
    for(const auto& record : list) { // iterate map
        if(!record.dirty())
            continue;
        sqlite3_bind(); // bind record fields
        sqlite3_step(); // execute sql 
        sqlite3_reset(); // reset
    }
    sqlite3_finalize();
}

main() {
    while(1) {
        read();
        writeDB();
    }
}

我最初的计划是在 for 循环中生成一个新线程,它将并行写入数据库中的每条记录。有两个问题。

1) 可能需要实现数据库锁定。

2) sqlitebind(), step() and reset()对同一条语句进行操作。因此,必须按顺序写入记录。

我正在使用 C++ 17。关于使数据库调用异步的任何建议?感谢您的帮助!

4

1 回答 1

2

您不必实现锁定。SQLite 确实提供了 ACID 保证,这意味着您不必围绕插入实现锁定。

话虽如此,为每个插入操作生成一个线程肯定是矫枉过正。您可以考虑将列表拆分为与机器上的内核数相等的部分,并执行 N 个并行循环以插入。但在我看来,除此之外的任何事情都可能是矫枉过正。

但不要认为我的话是理所当然的。考虑检测您的代码并对您现在拥有的单线程版本以及您可能选择的任何并行实现进行基准测试。您可以测试各种线程数(但请记住,多线程代码性能和可用内核数之间存在关系)以及并发实现:C++ 17 std 并行执行或 boost 变体等.

于 2019-10-12T22:43:22.730 回答