performance - SQLite 对大时序数据的适用性/性能

标签 performance sqlite

我有时间序列数据,我想将其存储在以下格式的数据库中:

  • 组:字符串
  • 日期:日期
  • val1 : 数量
  • val2 : 数字
  • ... 值

这个数据库将几乎全部读取。搜索将针对属于某个日期范围内的组的行(例如,group = XXX and date >= START and date <= END)。

数据集很大。数亿行。 SQLite 能轻松处理这种数据吗? SQLite 的吸引人之处在于它是无服务器的,如果可以的话我想使用它。

最佳答案

更新的答案

我尝试将 1 亿条记录的数据库放在 RAM 磁盘上——我不是指内存数据库,我的意思是将 RAM 格式化为一个文件系统,上面有一个数据库,同样的查询需要 11 秒而不是 147 秒秒像下面!!!如果正如您所说,您的查询大部分是只读的,这可能是您的一个选择 - 您可以在早上将数据库从磁盘复制到 RAMdrive 并整天在 RAMdrive 上快速访问它,或者直到重新启动,如果停电或机器崩溃,不用担心丢失它。然后,您可以对基于磁盘的副本运行任何写入操作,并且它会在您下次将数据库复制到 RAM 时随时反射(reflect)更改。

原始答案

我根据您的需求创建了三个测试数据库,并使用以下 Perl 代码分别在每个数据库中插入了 100 万、1000 万和 1 亿条记录。我只是用前缀“GROUP-”和记录号合成了组名,并生成了 1900 到 2000 之间的随机日期,值数据是随机的。

#!/usr/bin/perl
use strict;
use DBI;

my $dsn = "dbi:SQLite:dbname=test.db";
my $user = '';
my $password = '';
my %attr = ( RaiseError => 1, AutoCommit => 0 );

my $dbh = DBI->connect($dsn, $user, $password, \%attr) 
    or die "Can't connect to database: $DBI::errstr";

    $dbh->do("DROP TABLE IF EXISTS TimeSeries;");
    $dbh->do("CREATE TABLE TimeSeries (grp TEXT, date TEXT, val1 INTEGER, val2 INTEGER, val3 INTEGER, val4 INTEGER, PRIMARY KEY(grp,date))");

my $sql = qq{ INSERT INTO TimeSeries VALUES ( ?, ?, ?, ?, ?, ? ) };
my $sth = $dbh->prepare( $sql );

for(my $i=0;$i<100000000;$i++){
      # Synthesize a group
      my $group=sprintf("GROUP-%d",$i);
      $sth->bind_param(1,$group);

      # Generate random date between 1900-2000
      my $year=int(rand(100))+1900;
      my $month=int(rand(12))+1;
      my $day=int(rand(28)+1);
      my $date=sprintf("%d-%02d-%02d 00:00:00.0",$year,$month,$day);
      $sth->bind_param(2,$date);

      $sth->bind_param(3,int(rand(1000000)));
      $sth->bind_param(4,int(rand(1000000)));
      $sth->bind_param(5,int(rand(1000000)));
      $sth->bind_param(6,int(rand(1000000)));
      $sth->execute();
      if(($i % 1000)==0){printf "$i\n";$dbh->commit();}
}
$dbh->commit();
$sth->finish();
$dbh->disconnect();

对于 1m、10m 和 100m 的记录,文件大小如下所示:

-rw-r--r--  1 mark  staff   103M  4 Feb 14:16 1m.db
-rw-r--r--  1 mark  staff   1.0G  4 Feb 14:18 10m.db
-rw-r--r--  1 mark  staff    11G  4 Feb 15:10 100m.db

一些随机记录看起来像这样:

GROUP-794|1927-12-14 00:00:00.0|233545|700623|848770|61504
GROUP-797|1927-06-13 00:00:00.0|315357|246334|276825|799325
GROUP-840|1927-09-28 00:00:00.0|682335|5651|879688|247996
GROUP-907|1927-05-19 00:00:00.0|148547|595716|516884|820007
GROUP-1011|1927-06-01 00:00:00.0|793543|479096|433073|786200

然后我尝试查询 1927 年以来的所有记录,如下所示:

time sqlite3 1m.db 'select * from timeseries where date between "1927-01-01" and "1927-12-31"'

查询次数如下:

all records in year 1927 from 1m record database => 2.7 seconds
all records in year 1927 from 10m record database => 14 seconds
all records in year 1927 from 100m record database => 147 seconds

这些数字对我来说看起来很线性,但这是一个简单的测试,您可能想要获取代码并进一步尝试......

附言我在配备 SSD 的规范相当不错的 iMac 上运行。

关于performance - SQLite 对大时序数据的适用性/性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35167277/

相关文章:

android - 定期编辑 SharedPreferences 有什么缺点吗?

database - Sqlite 中的 LIKE 运算符,空格字符除外

android - 重新打开已经关闭

java - SQL - 按日期循环行的最佳实践方法

R 效率挑战 : Splitting a long character vector

javascript - Angular 事件(ng-keydown)内存泄漏

python - 用于选择数据的 Pandas 源

c# - Hangfire 作业插入对应用程序 API 性能的影响

ruby-on-rails - RoR/Heroku : detected sqlite3 gem which is not supported on heroku

android - SQLite 数据库 : unknown error (code 14): Could not open database