sql - SQLite 可以处理 9000 万条记录吗?

标签 sql sqlite

或者我应该使用不同的锤子来解决这个问题。

我有一个非常简单的数据存储用例,实际上是一个稀疏矩阵,我试图将其存储在 SQLite 数据库中。我创建了一个表:

create TABLE data ( id1 INTEGER KEY, timet INTEGER KEY, value REAL )

我向其中插入大量数据(每 10 分钟 800 个元素,每天 45 次),一年中的大部分时间。 (id1,timet) 的元组将始终是唯一的。

时间值是自纪元以来的秒数,并且会一直增加。出于所有实际目的,id1 是一个随机整数。虽然可能只有 20000 个唯一 ID。

然后我想访问 id1==someid 的所有值或访问 timet==sometime 的所有元素。在我通过 Linux 上的 C 接口(interface)使用最新 SQLite 的测试中,查找其中一个(或此查找的任何变体)大约需要 30 秒,这对于我的用例来说不够快。

我尝试为数据库定义一个索引,但这使插入速度减慢到完全不可行的速度(虽然我可能做错了......)

上表导致对任何数据的访问都非常缓慢。我的问题是:

  • SQLite 完全是错误的工具吗?
  • 我可以定义索引来显着加快处理速度吗?
  • 我应该为此使用 HDF5 之类的东西而不是 SQL 吗?

请原谅我对 SQL 的非常基础的理解!

谢谢

我提供了一个代码示例,展示了使用索引时插入速度如何变慢。使用“create index”语句,代码需要 19 分钟才能完成。没有它,它会在 18 秒内运行。


#include <iostream>
#include <sqlite3.h>

void checkdbres( int res, int expected, const std::string msg ) 
{
  if (res != expected) { std::cerr << msg << std::endl; exit(1); } 
}

int main(int argc, char **argv)
{
  const size_t nRecords = 800*45*30;

  sqlite3      *dbhandle = NULL;
  sqlite3_stmt *pStmt = NULL;
  char statement[512];

  checkdbres( sqlite3_open("/tmp/junk.db", &dbhandle ), SQLITE_OK, "Failed to open db");

  checkdbres( sqlite3_prepare_v2( dbhandle, "create table if not exists data ( issueid INTEGER KEY, time INTEGER KEY, value REAL);", -1, & pStmt, NULL ), SQLITE_OK, "Failed to build create statement");
  checkdbres( sqlite3_step( pStmt ), SQLITE_DONE, "Failed to execute insert statement" );
  checkdbres( sqlite3_finalize( pStmt ), SQLITE_OK, "Failed to finalize insert");
  checkdbres( sqlite3_prepare_v2( dbhandle, "create index issueidindex on data (issueid );", -1, & pStmt, NULL ), SQLITE_OK, "Failed to build create statement");
  checkdbres( sqlite3_step( pStmt ), SQLITE_DONE, "Failed to execute insert statement" );
  checkdbres( sqlite3_finalize( pStmt ), SQLITE_OK, "Failed to finalize insert");
  checkdbres( sqlite3_prepare_v2( dbhandle, "create index timeindex on data (time);", -1, & pStmt, NULL ), SQLITE_OK, "Failed to build create statement");
  checkdbres( sqlite3_step( pStmt ), SQLITE_DONE, "Failed to execute insert statement" );
  checkdbres( sqlite3_finalize( pStmt ), SQLITE_OK, "Failed to finalize insert");

  for ( size_t idx=0; idx < nRecords; ++idx)
  {
    if (idx%800==0)
    {
      checkdbres( sqlite3_prepare_v2( dbhandle, "BEGIN TRANSACTION", -1, & pStmt, NULL ), SQLITE_OK, "Failed to begin transaction");
      checkdbres( sqlite3_step( pStmt ), SQLITE_DONE, "Failed to execute begin transaction" );
      checkdbres( sqlite3_finalize( pStmt ), SQLITE_OK, "Failed to finalize begin transaction");
      std::cout << "idx " << idx << " of " << nRecords << std::endl;
    }

    const size_t time = idx/800;
    const size_t issueid = idx % 800;
    const float value = static_cast<float>(rand()) / RAND_MAX;
    sprintf( statement, "insert into data values (%d,%d,%f);", issueid, (int)time, value );
    checkdbres( sqlite3_prepare_v2( dbhandle, statement, -1, &pStmt, NULL ), SQLITE_OK, "Failed to build statement");
    checkdbres( sqlite3_step( pStmt ), SQLITE_DONE, "Failed to execute insert statement" );
    checkdbres( sqlite3_finalize( pStmt ), SQLITE_OK, "Failed to finalize insert");

    if (idx%800==799)
    {
      checkdbres( sqlite3_prepare_v2( dbhandle, "END TRANSACTION", -1, & pStmt, NULL ), SQLITE_OK, "Failed to end transaction");
      checkdbres( sqlite3_step( pStmt ), SQLITE_DONE, "Failed to execute end transaction" );
      checkdbres( sqlite3_finalize( pStmt ), SQLITE_OK, "Failed to finalize end transaction");
    }
  }

  checkdbres( sqlite3_close( dbhandle ), SQLITE_OK, "Failed to close db" ); 
}

最佳答案

您是一次插入所有 800 个元素吗?如果是,在事务中执行插入将显着加快该过程。

参见 http://www.sqlite.org/faq.html#q19

SQLite 可以处理非常大的数据库。参见 http://www.sqlite.org/limits.html

关于sql - SQLite 可以处理 9000 万条记录吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3160987/

相关文章:

mysql - 查询获取数字显示了多少次

c# - 在 C# 和 DB 中创建 Guid 键之间的区别

IN() 中的 MySQL 子查询

java - SQLite 查询读取错误的 Id

java - 为类的任何函数编写可线程包装器?

python - 文件系统中的 ACID 事务

python - 在之前都没有的地方出现语法错误

sql - 读取 XML 列

SQL Server 2008 列名 'Type' 未显示在更新查询中

java - 更新版本并将共享首选项转储到数据库中