C++程序中使用Sqlite3 blob的RAM消耗

6
我在一个C++程序中使用sqlite3数据库管理系统,主要用于将文件存储为blob对象(我知道这不是最好的选择)。显然,由于它们有时会很大(40-80MB),因此我会逐步地写入它们,为此我必须首先使用绑定函数sqlite3_bind_zeroblob(...)创建一个占位符,然后打开blob进行递增式写入和读取。
我面临的问题是,在创建blob占位符时(在sqlite3_step期间),我的应用程序的RAM消耗会在2-3秒内达到80-160MB,一旦创建完成,RAM消耗就会回到2-3MB左右。我不知道为什么!如果他们已经创造了一种逐步写入blob的方法,那么一定有一种方法可以创建那个愚蠢的占位符而不浪费160MB的RAM,但我没有找到。你有什么建议吗?
sqlite3_stmt* stm = NULL;
sqlite3_blob *BLOB = NULL;

rc = sqlite3_prepare_v2(db, sql.c_str(), -1, &stm, NULL);

rc = sqlite3_bind_blob(stm, 1, wpath.c_str(), wpath.size()*sizeof(wchar_t), SQLITE_STATIC);
rc = sqlite3_bind_text(stm, 2, hash.c_str(), hash.size(), SQLITE_STATIC);
rc = sqlite3_bind_zeroblob(stm, 3, size);
rc = sqlite3_bind_int(stm, 4, versione);
rc = sqlite3_bind_blob(stm, 5, last.c_str(), last.size()*sizeof(wchar_t), SQLITE_STATIC);

rc = sqlite3_step(stm);

if (rc != SQLITE_DONE) {
    fprintf(stderr, " This file was already present in the database!\n", rc);
    return;
}
else {
    fprintf(stdout, "Record FILE created successfully\n");
}

也许这是零写入缓存的使用,尝试将缓存大小设置为最小值? - fghj
什么是SQL查询? - CL.
我修改了缓存值,但似乎没有任何变化。无论如何,SQL查询是以下的std :: string sql =“INSERT INTO FILES(PATH,HASH,DATI,VER,LAST)VALUES(?1,?2,?3,?4,?5);”。 - GalloCedrone
我在问题中写了,首先我需要创建占位符(第三个参数),然后打开它并使用增量I/O进行写入,问题是创建占位符会浪费很多RAM。从文档中可以看到-->“Zeroblob旨在用作BLOB的占位符,其内容稍后使用增量BLOB I/O例程编写。 zeroblob的负值导致长度为零的BLOB。”也许您被第五个参数的绑定所困扰。 - GalloCedrone
问题是有时候我没有那么多的可用内存(它曾经在一块只有256MB的RAM上运行),这就是为什么我会逐步写入数据,一旦我收到了数据@1201ProgramAlarm。 - GalloCedrone
显示剩余4条评论
1个回答

3
这是一个与这里报告的问题有关的IT技术内容。
官方答案如下:

为了使zeroblobs像上述方式一样工作(使用固定数量的内存来存储,无论它们有多大),所有的zeroblobs必须位于行的末尾。换句话说,接收zeroblobs的表列必须是表中的最后一列。如果任何非零内容跟在zeroblob之后,那么zeroblob会扩展成一个字面上由零字节组成的序列,这意味着必须为整个zeroblob分配内存。

所以你需要改变顺序来解决这个问题。
sqlite3_stmt* stm = NULL;
sqlite3_blob *BLOB = NULL;

rc = sqlite3_prepare_v2(db, sql.c_str(), -1, &stm, NULL);

rc = sqlite3_bind_blob(stm, 1, wpath.c_str(), wpath.size()*sizeof(wchar_t), SQLITE_STATIC);
rc = sqlite3_bind_text(stm, 2, hash.c_str(), hash.size(), SQLITE_STATIC);
rc = sqlite3_bind_int(stm, 3, versione);
rc = sqlite3_bind_blob(stm, 4, last.c_str(), last.size()*sizeof(wchar_t), SQLITE_STATIC);
rc = sqlite3_bind_zeroblob(stm, 5, size);

rc = sqlite3_step(stm);

if (rc != SQLITE_DONE) {
    fprintf(stderr, " This file was already present in the database!\n", rc);
    return;
}
else {
    fprintf(stdout, "Record FILE created successfully\n");
}

非常感谢,我知道那种行为有一个解释和可能的解决方案! - GalloCedrone

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接