【发布时间】:2021-01-30 18:13:14
【问题描述】:
我正在编写一个程序,我必须从数据库(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, 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", NULL, NULL, &sErrMsg);
sqlite3_finalize(stmt);
【问题讨论】:
-
首先使用普通的prepared statement api 而不是
sqlite3_exec()。 -
我试过了,但我没有更好的结果(我使用 sqlite3_exec("SELECT ZPOS FROM PLANT_DATA WHERE ID = ?") )而且stackoverflow.com/questions/1703203/…
-
你能提供确切的查询吗?我最好的猜测是你应该在第二列上添加一个索引。如果您使用第二列应用
WHERE子句或ORDER BY子句,则对该列进行索引将使其 millions of times faster 可供读取。 -
我尝试在第一列上应用索引,但性能相同...
-
你真的需要每秒读取所有数据吗?您的窗口可能不会同时显示 1000 万个数字。
标签: c++ database performance sqlite query-optimization