如何储存73亿行市场数据(优化可读)?

我有一个自1998年以来的1000股1分钟数据的数据集,总计(2012-1998)*(365*24*60)*1000 = 7.3 Billion行左右。

大部分(99.9%)的时间我只执行读取请求。

将数据存储在数据库中的最佳方法是什么?

  • 1个7.3B行的大桌子?
  • 1000个表(每个股票代码一个),每个7.3M行?
  • 任何数据库引擎的build议? (我打算使用Amazon RDS的MySQL)

我不习惯处理这么大的数据集,所以这是一个很好的学习机会。 我会很感激你的帮助和build议。

编辑:

这是一个样本行:

'XX',20041208,938,43.7444,43.7541,43.735,43.7444,35116.7,1.0,0

第1列是股票代号,第2列是date,第3列是分钟,其余是开高 – 低收盘价格,成交量和3个整数列。

大部分查询将会像“给我AAPL的价格之间2012年4月12日12:15和2012年4月13日12:52”

关于硬件:我计划使用Amazon RDS,所以我对此非常灵活

告诉我们关于查询和你的硬件环境。

只要可以利用并行性,我就会非常想去NoSQL ,使用Hadoop或类似的东西。

更新

好吧,为什么?

首先,请注意我询问了有关的疑问。 你不能 – 而且我们当然不能 – 在不知道工作量是什么的情况下回答这些问题。 (我会偶然地有一篇关于这个出现的文章,但是我今天不能把它连接起来)。但是这个问题的严重性让我想到了摆脱旧大数据库的考虑,

  • 我对类似系统的经验表明,访问要么是大序列(计算某种时间序列分析),要么是非常灵活的数据挖掘(OLAP)。 顺序数据可以顺序处理得更好更快, OLAP意味着计算大量和大量的索引,这要么耗费大量的时间,要么占用大量的空间。

  • 但是,如果您正在对OLAP领域的许多数据进行有效的大规模运行,那么面向列的方法可能是最好的。

  • 如果你想做随机查询,特别是进行交叉比较,Hadoop系统可能是有效的。 为什么? 因为

    • 您可以更好地利用相对较小的商品硬件的并行性。
    • 还可以更好地实现高可靠性和冗余
    • 许多这些问题自然适用于MapReduce范例。

但事实是,直到我们知道你的工作量,不可能说任何明确的。

所以数据库适用于你有一个不断变化的大型复杂模式的情况。 你只有一个带有简单数字字段的“表”。 我会这样做:

准备一个C / C ++结构来保存logging格式:

 struct StockPrice { char ticker_code[2]; double stock_price; timespec when; etc }; 

然后计算sizeof(StockPrice [N]),其中N是logging数。 (在一个64位的系统)它应该只有几百演出,​​适合一个50美元的硬盘。

然后截断一个文件到这个大小和mmap(在Linux上,或使用窗口上的CreateFileMapping)到内存:

 //pseduo-code file = open("my.data", WRITE_ONLY); truncate(file, sizeof(StockPrice[N])); void* p = mmap(file, WRITE_ONLY); 

将mmaped指针转换为StockPrice *,并将数据传递给数组。 closuresmmap,现在你可以将数据放在一个文件中的一个大的二进制数组中,以后可以再次进行转换。

 StockPrice* stocks = (StockPrice*) p; for (size_t i = 0; i < N; i++) { stocks[i] = ParseNextStock(stock_indata_file); } close(file); 

您现在可以再次从任何程序中将其再次映射为只读,并且您的数据将随时可用:

 file = open("my.data", READ_ONLY); StockPrice* stocks = (StockPrice*) mmap(file, READ_ONLY); // do stuff with stocks; 

所以,现在你可以把它看作是一个内存数组结构。 你可以根据你的“查询”来创build各种索引数据结构。 内核将处理交换数据到/从磁盘透明,所以它会非常快速。

如果您希望有一个特定的访问模式(例如连续的date),最好按照该顺序对数组进行sorting,以便顺序地访问磁盘。

这是我的理解, HDF5是专门devise的库存数据的时间序列存储作为一个潜在的应用程序。 研究人员已经certificateHDF5对于大量数据是有利的: 染色体 , 物理学 。

好的,所以这与其他答案有所不同,但是…对于我来说,如果您在文件系统中拥有数据(每个文件有一个库存,也许)具有固定的logging大小,那么您可以获取数据非常容易:给定一个特定的股票和时间范围的查询,你可以寻find正确的地方,获取所有你需要的数据(你会知道到底有多less字节),将数据转换成你需要的格式(可以取决于你的存储格式是非常快的),而你离开了。

我对亚马逊的存储空间一无所知,但是如果你没有直接访问文件的东西,那么基本上可能会有斑点 – 你需要平衡大的斑点(更less的logging,但可能读取的数据比你需要的多)时间)与小blob(更多的logging提供更多的开销,可能更多的请求来获得他们,但更less的无用的数据每次返回)。

接下来,你添加caching – 我build议给不同的服务器不同的股票来处理例如 – 你几乎可以从内存中提供服务。 如果你能够在足够的服务器上负担足够的内存,那么就绕过“按需加载”部分,并在启动时加载所有的文件。 这样会简化一些工作,但代价是启动速度较慢(这显然会影响故障切换,除非您可以负担总是有两台服务器的任何特定的库存,这将是有益的)。

请注意,您不需要为每个logging存储股票代码,date或分钟,因为它们隐含在您正在加载的文件中以及文件中的位置。 你还应该考虑每个值需要多less准确性,以及如何高效地存储 – 你已经给你的问题提供了6SF,你可以用20位存储。 可能将三个20位整数存储在64位存储器中:将其读取为long整型(或​​任何您的64位整数值),并使用掩码/移位将其恢复为三个整数。 你当然需要知道使用什么规模 – 如果你不能使它保持不变,那么你可能需要用备用的4位来编码。

你还没有说其他三个整数列是什么样的,但是如果你可以用这三个整数的64位来获得,你可以存储16个字节的整个logging​​。 对于整个数据库来说,这只是〜110GB,这并不是真的太…

编辑:另一件要考虑的事情是,大概这个股票在周末没有变化 – 甚至是一夜之间。 如果股票市场每周只有8个小时,每周5天,那么你只需要每星期40个价值,而不是168个。那时,你的文件中只有大约28GB的数据,比你原先想象的要小得多。 在内存中拥有这么多的数据是非常合理的。

编辑:我想我已经错过了为什么这种方法是一个很好的适合在这里解释:你有一个非常可预测的方面,大部分的数据 – 股票代码,date和时间。 通过表示一次 (作为文件名)并将date/时间完全隐含在数据的位置 ,您将删除大量的工作。 这有点像String[]Map<Integer, String>之间的区别 – 知道你的数组索引总是从0开始,以1为增量递增,直到数组的长度允许快速访问和更高效存储。

我有一个1分钟数据的数据库,其中1000个股票中的大部分(99.9%)将只执行读取请求。

一次存储和多次读取基于时间的数字数据是一个称为“时间序列”的用例。 其他常见的时间序列是物联网中的传感器数据,服务器监控统计,应用事件等。

这个问题在2012年被问到,从那以后,一些数据库引擎一直在开发专门用于pipe理时间序列的function。 InfluxDB是开放源代码的,用Go语言编写的,还有麻省理工学院许可的。

InfluxDB专门针对时间序列数据进行了存储和查询。 比Cassandra更受欢迎 , Cassandra经常被吹捧为存储时间序列的伟大之处:

InfluxDB与Cassandra的查询速度

对时间序列进行优化需要一定的权衡。 例如:

对现有数据的更新是很less见的,有争议的更新永远不会发生。 时间序列数据主要是从未更新的新数据。

Pro:限制对更新的访问可以提高查询和写入性能

Con:更新function受到很大限制

在开放源代码基准中 ,

在三项testing中,InfluxDB的性能都超过了MongoDB,吞吐量提高了27倍,而磁盘空间减less了84倍,并且在查询速度方面性能相对相当。

InfluxDB与MongoDB磁盘存储要求和压缩

查询也非常简单。 如果你的行看上去像是<symbol, timestamp, open, high, low, close, volume> ,那么InfluxDB就可以存储它,然后很容易地进行查询。 说,在过去的10分钟的数据:

 SELECT open, close FROM market_data WHERE symbol = 'AAPL' AND time > '2012-04-12 12:15' AND time < '2012-04-13 12:52' 

没有ID,没有键,也没有连接。 你可以做很多有趣的聚合 。 您不必像PostgreSQL一样对表进行垂直分区 ,或者像MongoDB一样将您的模式压缩到秒数组中 。 此外,InfluxDB压缩得非常好,而PostgreSQL将无法对您所拥有的数据types进行任何压缩 。

以下是在Microsoft SQL Server 2012数据库之上创build市场数据服务器的尝试,该数据库应该适用于免费的开源项目OLAP分析:

http://github.com/kriasoft/market-data

我build议你看看apache solr ,我认为这对你的特定问题是非常理想的。 基本上,你会首先索引你的数据(每行是一个“文档”)。 Solr针对search进行了优化,本地支持date范围查询。 你的名义查询,

"Give me the prices of AAPL between April 12 2012 12:15 and April 13 2012 12:52"

会翻译成类似于:

 ?q=stock:AAPL AND date:[2012-04-12T12:15:00Z TO 2012-04-13T12:52:00Z] 

假设“股票”是股票名称,“date”是从input数据的索引中的“date”和“分钟”列创build的“DateField”。 Solr是非常灵活的,我真的不能说足够的好东西。 因此,例如,如果您需要维护原始数据中的字段,则可能会find一种方法来dynamic创build“DateField”作为查询(或filter)的一部分。

首先,今年没有365个交易日,假期52个周末(104)= 250×实际的日间市场开放时间像某人所说的那样,并且使用该符号作为主键不是一个好主意因为符号改变了,所以使用符号(char)的k_equity_id(数字),因为符号可以像这样A,或者GAC-DB-B.TO,那么在你的价格信息的数据表中,你有,所以你的估计值为7.3十亿是大大超过计算,因为它是14年每个符号约170万行。

k_equity_id k_date k_minute

和EOD表(这将被视为1000倍的其他数据)

k_equity_id k_date

其次,不要把你的OHLC的分钟数据存储在同一个数据库表和EOD表(一天的结束)中,因为任何人在一年中想要查看一个pnf或折线图,都没有兴趣分钟的信息。

我认为任何主要的RDBMS都可以处理这个问题。 在primefaces级别,正确​​分区的表格似乎是合理的(如果修复的话,根据您的数据使用进行分区 – 这可能是符号或date)。

您还可以查看构build聚合表以便在primefaces级别之上进行更快的访问。 例如,如果您的数据是在白天,但您经常将数据返回到wekk甚至月份级别,则可以在聚合表中预先计算。 在一些数据库中,这可以通过一个caching视图来完成(不同的DB解决scheme的不同名称 – 但基本上它是对primefaces数据的一个视图,但是一旦运行该视图被caching/强化到一个固定的临时表中 – 为子查询匹配查询。这可以间隔下降以释放内存/磁盘空间)。

我想我们可以帮助您更多地了解数据使用情况。

如果你有硬件,我推荐MySQL Cluster 。 您可以获得熟悉的MySQL / RDBMS接口,并且可以快速并行写入。 由于networking延迟,读取速度将比常规MySQL慢,但由于MySQL簇和NDB存储引擎的工作方式,您可以并行查询和读取。

确保你拥有足够的MySQL Cluster机器和足够的内存/内存,但是MySQL Cluster是一个面向内存的数据库体系结构。

或Redis ,如果你不介意你的读/写的键/值/ NoSQL接口。 确保Redis具有足够的内存 – 它的读写速度超快,您可以使用它进行基本查询(但不包括RDBMS),但也是内存数据库。

就像其他人所说的,了解更多关于你将要运行的查询将会有所帮助。

您应该比较缓慢的解决scheme与一个简单的优化内存模型。 无压缩,适合于256 GB的内存服务器。 一个快照适合于32 K,你只需要在date时间和股票上进行位置索引。 然后,您可以制作专门的快照,因为开启一个往往等于closures前一个。

为什么你认为使用数据库是完全有意义的(rdbms或者nosql)? 这个数据不会改变,它适合内存。 这不是dbms可以增加值的用例。

如果你的用例是简单地读取没有聚集的行,你可以使用Aerospike集群。 内存数据库支持文件系统的持久性。 这也是SSD优化。

如果您的用例需要聚合数据,请使用date范围分片的MongoDB集群。 你可以把一年的老虎钳数据放在碎片里。

你会希望数据存储在一个列式表/数据库中 。 像Vertica和Greenplum这样的数据库系统是列式数据库,我相信SQL Server现在允许列式表格。 这些对于从非常大的数据集中SELECT非常有效。 它们在导入大型数据集时也很有效率。

一个免费的柱状数据库是MonetDB 。