4

我以原始形式(csv 和二进制)积累了相当多的数据——准确地说是几个月每天 4GB。

我决定加入文明世界并使用数据库来访问数据,我想知道正确的布局是什么;格式非常简单:每次报价几行(出价、要价、时间戳等)x 高达 50 万/天 x 数百种金融工具 x 月数据。

在商品硬件(2 x 1GB RAID 0 SATA,核心 2 @ 2.7GHz)上运行有一个带有 MYISAM 的 MySQL 服务器(我理解这将是此类使用的正确引擎)

数据库的正确布局是什么?表格/索引应该是什么样子?这种情况的一般建议是什么?你会预测什么会让我在此过程中陷入陷阱?

编辑:我的常见用法是提取特定日期和仪器的时间序列信息的简单查询,例如

SELECT (ask + bid) / 2
  WHERE instrument='GOOG'
  AND date = '01-06-2008'
  ORDER BY timeStamp;

编辑:我试图将我的所有数据填充到一个由 timeStamp 索引的表中,但它太慢了 - 因此我认为它需要一个更复杂的方案。

4

6 回答 6

7

您并没有真正说出您的背景以及您对编程和数据库设计的了解程度。听起来你应该做一些阅读。从概念上讲,尽管您的设计相当简单。您的描述仅确定了两个实体:

  • 金融工具;和
  • 引用。

所以你需要然后识别属性。

金融工具:

  • 安全码;
  • 市场;
  • 等等

引用:

  • 时间戳;
  • 金融工具;
  • 竞标价格; 和
  • 问价格。

对金融工具的引用就是所谓的外键。每个表还需要一个主键,可能只是一个自增字段。

概念上相当简单。

CREATE TABLE instrument (
  id BIGINT NOT NULL AUTO_INCREMENT,
  code CHAR(4),
  company_name VARCHAR(100),
  PRIMARY KEY (id)
);

CREATE TABLE quote (
  id BIGINT NOT NULL AUTO_INCREMENT,
  intrument_id BIGINT NOT NULL,
  dt DATETIME NOT NULL,
  bid NUMERIC(8,3),
  ask NUMERIC(8,3),
  PRIMARY KEY (id)
)

CREATE INDEX instrument_idx1 ON instrument (code);

CREATE INDEX quote_idx1 ON quote (instrument_id, dt);

SELECT (bid + ask) / 2
FROM instrument i
JOIN quote q ON i.id = q.instrument_id
WHERE i.code = 'GOOG'
AND q.dt >= '01-06-2008' AND q.dt < '02-06-2008'

如果您的数据集足够大,您可能希望在表中包含 (bid + ask) / 2,这样您就不必即时计算。

好的,这就是标准化视图。在此之后,您可能需要开始进行性能优化。考虑这个关于在 MySQL 中存储数十亿行的问题。分区是 MySQL 5.1+ 的一个特性(相当新)。

但是要问自己的另一个问题是:您需要存储所有这些数据吗?我问这个的原因是我以前从事在线经纪工作,我们只在一个非常有限的窗口中存储所有交易,交易将是比报价更小的数据集,你似乎想要的。

存储数十亿行数据是一个严重的问题,您确实需要认真的帮助来解决这个问题。

于 2008-12-29T10:04:54.010 回答
2

您需要做的是阅读数据库规范化。如果你觉得那篇文章太多,你应该简单地浏览一下第三范式教程。

于 2008-12-29T10:10:47.010 回答
2

当在报价级别存储数据时,许多金融数据库至少按工具对数据进行分区,因为很少需要跨工具运行查询。所以每个仪器一张桌子是正常的。有些更进一步,还按日期进行分区,为每个仪器/日期组合提供一个表格。如果跨日期查询是常态,这会使查询变得更加困难。

所以有两个选择:

  1. 每个工具都有一个刻度表,时间戳上有一个聚集索引
  2. 每个工具/日期的刻度表,时间戳上有一个聚集索引

这是访问速度和查询方便性之间的基本权衡。

于 2008-12-29T10:45:31.103 回答
1

或者也许考虑一个星型模式、维度和事实。Ralph Kimball 有一些好东西可以告诉你如何去做。

于 2008-12-29T14:41:44.403 回答
1

Dani,我多年来一直在与 Tick by Tick data 合作,并且很乐意在这方面进行合作。在 Hotmail 给我发电子邮件给 IanTebbutt。(顺便说一句,我已经检查过了,没有办法在 StackOverflow 上发送私人电子邮件,而 Jeff 似乎反对它被拒绝,。)

简而言之,我发现按日期和仪器进行分区效果很好。您可以选择使用 InstrumentX_YYDD 之类的模式将仪器 X 的一个月数据放入一组表中。然后在访问数据时,您至少需要一个表名生成器,但更可能是一个 sql 生成器,它可以决定使用哪个表,或者可能使用联合来查看多个表。

无论您如何看待这些数据量都不容易处理。这接近于 DataWarehouse 领域,并且有很多方法可以剥去那只猫的皮。就像我说的,很高兴合作 - 我可能已经解决了一半的问题。

于 2009-01-18T02:42:47.770 回答
0

只是一些一般性的观察:

  • 不要使用TIMESTAMP列,因为它是根据INSERT时间自动设置的。由于您正在导入数据,这不是您想要的。
  • 如果使用 MySQLDATETIME列类型,则可以在其上使用 MySQL日期和时间函数
  • MyISAM 不支持FOREIGN KEY约束并默默地忽略它们。
  • 索引,索引,索引。确保将它们放在将用于查找的列上。但是,如果您有包含大量文本的列,您可能希望对它们使用FULLTEXT搜索
  • 如果你打算把它变成一个带有INSERTs 和SELECT查询的实时数据库,考虑使用带有事务和行级锁定的 InnoDB ( SELECT ... FOR UPDATE)
于 2008-12-29T15:19:17.073 回答