如何解决减少读取数据库所需的时间
我正在编写一个程序,我必须从数据库 (Sqlite) 中读取大量数据,然后在窗口中显示获得的值。我需要每秒刷新窗口,因此读取所有数据的操作需要持续不到一秒。
数据库由两列组成,一个主键和一个我想显示的值(一个数字),主键只是一个从 1 到行数的累进数字。主键对我来说并不重要,因为检索到的数据在向量/结构中排序。
数据库大约有 8*10^7 行,它在磁盘上的大小约为 250MB。
我的想法是通过事务可以减少读取数据所需的时间,我尝试实现一个小程序并测量时间,大约为 20 秒。然后我了解到使用 select 语句 (Here)
时事务不是很有效所以我尝试:
using Record = std::vector<std::string>;
using Records = std::vector<Record>;
int select_callback(void *p_data,int num_fields,char **p_fields,char **p_col_names)
{
Records* records = static_cast<Records*>(p_data);
try {
records->emplace_back(p_fields,p_fields + num_fields);
}
catch (...) {
// abort select on failure,don't let exception propogate thru sqlite3 call-stack
return 1;
}
return 0;
}
Records select_stmt(const char* stmt)
{
Records records;
char *errmsg;
int ret = sqlite3_exec(db,stmt,select_callback,&records,&errmsg);
if (ret != SQLITE_OK) {
std::cerr << "Error in select statement " << stmt << "[" << errmsg << "]\n";
}
else {
std::cerr << records.size() << " records returned.\n";
}
return records;
}
Records records = select_stmt("SELECT * FROM TABLE");
我有最快的结果(大约 14 秒),但这还不够。
有没有可能达到这样的阅读时间(小于1秒)?
操作系统:Ubuntu 20.10 语言:C++
我用来通过prepare和transaction语句获取数据的代码
std::string msg = "SELECT ZPOS FROM TABLE WHERE ID = ?";
const char* msg_char_ptr = msg.c_str();
memset(sSQL,'\0',BUFFER_SIZE);
sprintf(sSQL,msg_char_ptr);
int rc = sqlite3_prepare_v2(db,sSQL,BUFFER_SIZE,&stmt,&tail);
int count = 0;
if(rc == SQLITE_OK ) {
sqlite3_exec(db,"BEGIN TRANSACTION",NULL,&sErrMsg);
for (int i = 0; i < number_of_rows; i++)
{
// indices vector with all the indices of the table
sqlite3_bind_int(stmt,1,indices[i]);
while ( sqlite3_step( stmt ) == SQLITE_ROW ) {
int result = sqlite3_column_int( stmt,0 );
// collectData vector with the result
collectData[count] = result;
int val = sqlite3_column_count( stmt );
count ++;
}
sqlite3_step(stmt);
sqlite3_clear_bindings(stmt);
sqlite3_reset(stmt);
}
} else {
printf("SQLite prepare error.\n");
}
sqlite3_exec(db,"END TRANSACTION",&sErrMsg);
sqlite3_finalize(stmt);
解决方法
如果您必须使用 SQL SELECT 多行,最好的办法是使用一个 SQL SELECT 语句在多行结果集中获取您想要的所有行。不要为您想要的每个 ID
值发出一个 SELECT,而是发出 SELECT ID,ZPOS FROM TABLE` 并设置您的代码以读取多行。
话虽如此,我猜您正在尝试每秒一次从您的表中将 80 兆行 (250MiB) 读取到您的应用程序中的 RAM 中。每秒读取的数据太多。即使您编写 C++ 代码只是为了打开一个平面文件并读取 250MiB,每秒执行一次也太频繁了。
要记住的一些设计要点:
-
SQL 中没有任何魔法可以使它访问大量数据超快,比读取文件更快。
-
SQL 的重点是允许像您这样的程序一次处理几行非常大的数据集。你当然可以做这样的事情
SELECT ID,ZPOS FROM TABLE WHERE ID > ?
您在
?
中绑定的值是您上次读取数据库时收到的最大 ID 值。这会让您获得新记录。 -
在此方面,您需要设计程序以将表中的数据缓存在 RAM 中并有效地使用缓存。一秒钟重新加载所有数据太频繁了。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。