c++ - 提高SQLite每秒更新的性能?

标签 c++ sqlite database-performance

我的问题直接来自 this一,虽然我只对感兴趣更新 仅此而已。

我有一个应用程序写在 C/C++大量使用 SQLite ,主要是 SELECT/UPDATE , 以非常频繁的间隔(每 0.5 到 1 秒大约 20 个查询)

我的数据库不大,大约 2500 目前记录,这里是表结构:

CREATE TABLE player (
   id INTEGER PRIMARY KEY AUTOINCREMENT,
   name VARCHAR(64) UNIQUE,
   stats VARBINARY,
   rules VARBINARY
);

到目前为止我还没有使用 transactions因为我正在改进代码并希望稳定性而不是性能。

然后我仅通过执行 10 update 来测量我的数据库性能。查询,以下(在不同值的循环中):
// 10 times execution of this
UPDATE player SET stats = ? WHERE (name = ?)

哪里stats是 150 个字符的 JSON 和 name是 5-10 个字符。

没有交易,结果是 Not Acceptable :- 大约 1 整秒(每个 0.096)

对于交易,时间下降了 x7.5 倍:- 大约 0.11 - 0.16 秒(每个 0.013)

我尝试删除数据库的很大一部分和/或重新排序/删除列以查看是否有任何更改,但没有更改。即使数据库只包含 ,我也会得到上述数字100 条记录 (已测试)。

然后我尝试玩 PRAGMA选项:
PRAGMA synchronous = NORMAL
PRAGMA journal_mode = MEMORY

给了我更小的时间,但并非总是如此,更像是 大约 0.08 - 0.14 秒
PRAGMA synchronous = OFF
PRAGMA journal_mode = MEMORY

终于给了我极小的次大约 0.002 - 0.003 秒 但我不想使用它,因为我的应用程序每秒都会保存数据库,并且很有可能在操作系统/电源故障时损坏数据库。

我的 C SQLite查询代码是:(注释/错误处理/无关部分省略)
// start transaction
sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, NULL);

// query
sqlite3_stmt *statement = NULL;
int out = sqlite3_prepare_v2(query.c_str(), -1, &statement, NULL);
// bindings
for(size_t x = 0, sz = bindings.size(); x < sz; x++) {
   out = sqlite3_bind_text(statement, x+1, bindings[x].text_value.c_str(), bindings[x].text_value.size(), SQLITE_TRANSIENT);
   ...
}

// execute
out = sqlite3_step(statement);

if (out != SQLITE_OK) {
   // should finalize the query no mind the error
   if (statement != NULL) {
      sqlite3_finalize(statement);
   }
} 

// end the transaction
sqlite3_exec(db, "END TRANSACTION", NULL, NULL, NULL);

如您所见,这是一个非常典型的 TABLE ,记录数很小,我正在做一个简单的UPDATE正好10次。我还能做些什么来减少我的 UPDATE次?我正在使用最新的 SQLite 3.16.2 .

NOTE: The timings above are coming directly from a single END TRANSACTION query. Queries are done into a simple transaction and i'm using a prepared statement.



更新:

我在启用和禁用事务以及各种更新计数的情况下执行了一些测试。我使用以下设置进行了测试:
VACUUM;
PRAGMA synchronous = NORMAL;  -- def: FULL
PRAGMA journal_mode = WAL;    -- def: DELETE
PRAGMA page_size = 4096;      -- def: 1024

结果如下:

无交易(10 次更新)
  • 0.30800 秒(每次更新 0.0308)
  • 0.30200 秒
  • 0.36200 秒
  • 0.28600 秒

  • 无交易(100 次更新)
  • 2.64400 秒(每次更新 0.02644)
  • 2.61200 秒
  • 2.76400 秒
  • 2.68700 秒

  • 无交易(1000 次更新)
  • 28.02800 秒(每次更新 0.028 秒)
  • 27.73700 秒
  • ..

  • 有交易(10 次更新)
  • 0.12800 秒(每次更新 0.0128)
  • 0.08100 秒
  • 0.16400 秒
  • 0.10400 秒

  • 有交易(100 次更新)
  • 0.088 秒(每次更新 0.00088)
  • 0.091 秒
  • 0.052 秒
  • 0.101 秒

  • 有交易(1000 次更新)
  • 0.08900 秒(每次更新 0.000089)
  • 0.15000 秒
  • 0.11000 秒
  • 0.09100 秒

  • 我的结论是 transactions time cost per query毫无意义.也许时间会随着大量更新而变得更大,但我对这些数字不感兴趣。单个事务的 10 次和 1000 次更新之间几乎没有时间成本差异。但是我想知道这是否是我机器上的硬件限制并且不能做太多。看来我不能低于~100使用单个事务和范围 10-1000 次更新的毫秒数,即使使用 WAL。

    如果没有交易,固定时间成本约为 0.025秒。

    最佳答案

    如此少量的数据,数据库操作本身的时间是微不足道的;您测量的是事务开销(强制写入磁盘所需的时间),这取决于操作系统、文件系统和硬件。

    如果您可以忍受它的限制(主要是没有网络),您可以通过启用 WAL mode 来使用异步写入。 .

    关于c++ - 提高SQLite每秒更新的性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42030790/

    相关文章:

    c++ - 重新定义类成员数据类型

    sql - 为什么 Oracle 使用 ORDER BY 忽略索引?

    jquery - 处理类似于 "StackoverflowQuestion tags"列表的正确方法

    sql - 在 PostgreSQL 中内部连接表时计数缓慢

    c++ - 实际应用过滤器的是什么?

    c++ - Visual C++ 库 DLL 是否已本地化?

    c++ - 如何在 OpenGL 中实现绘画(支持图层)?

    ios - swift - 来自预填充 SQLite 的 CoreData

    sqlite - 如何将 sqlite3 依赖项添加到 VS Code 扩展?

    java - 将java连接到sqlite的问题