数据库设计问题

时间:2008-12-29 09:52:43

标签: mysql database financial

我以原始形式(csv和二进制文件)累积了大量数据 - 每天4GB,准确几个月。

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

有一个带有MYISAM的MySQL服务器(我知道这种用法是正确的引擎)在商用硬件上运行(2 x 1GB RAID 0 SATA,核心2 @ 2.7GHz)

数据库的布局是什么?表/索引应该如何?这种情况的一般建议是什么?您预测会给我带来哪些陷阱?

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

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

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

6 个答案:

答案 0 :(得分:7)

你并没有真正说出你的背景是什么以及你对编程和database design了解多少。听起来你应该做一些阅读。从概念上讲,您的设计相当简单。您的描述只标识了两个实体:

  • 金融工具;和
  • 引用。

所以你需要确定属性。

金融工具:

  • 安全码;
  • 市场;

引用:

  • 时间戳;
  • 金融工具;
  • 买入价;和
  • 要价。

对金融工具的提及就是所谓的foreign key。每个表还需要一个primary key,可能只是一个自动增量字段。

概念上相当简单。

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,这样您就不必动态计算。

好的,这就是标准化视图。在此之后,您可能需要开始进行性能优化。考虑一下这个关于storing billions of rows in MySQL的问题。分区是MySQL 5.1+的一个特性(相当新)。

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

存储数十亿行数据是一个严重的问题,而且你真的需要认真帮助解决这个问题。

答案 1 :(得分:2)

您需要做的是阅读database normalization。如果您发现该文章太多,您应该浏览一下3rd normal form教程。

答案 2 :(得分:2)

当以刻度级别存储数据时,许多财务数据库至少通过工具对数据进行分区,因为很少需要跨仪器运行查询。因此每个工具的表格是正常的。有些更进一步,按日期划分,每个工具/日期组合给出一个表格。如果跨日期的查询是常态,这会使查询变得更加困难。

所以有两个选择:

  1. 每个工具的刻度表,时间戳上带有聚簇索引
  2. 每个工具/日期的刻度表,时间戳上有聚集索引
  3. 这是访问速度和查询简易性之间的基本权衡。

答案 3 :(得分:1)

或者考虑一下星型模式,维度和事实。 Ralph Kimball有一些nice stuff告诉你如何去做。

答案 4 :(得分:1)

达尼,     我多年来一直在使用Tick by Tick数据,我很乐意就此进行合作。给我发电子邮件IanTebbutt在Hotmail。 (顺便说一下,我已经检查过,并且无法在StackOverflow上发送私人电子邮件,杰夫似乎反对它rejected,。)

简单地说,我发现按日期划分和仪器可以很好地工作。您可以选择使用InstrumentX_YYDD等模式将仪器X的数月数据放入一组表中。然后在访问至少需要一个表名生成器的数据时,更可能是一个sql生成器,它可以决定使用哪个单表,或者可能使用Union查看多个表。

无论您如何看待这种数据量都不容易处理。这接近数据仓库领域,并且有很多方法可以为那只猫设置皮肤。就像我说的那样,很乐意合作 - 我可能已经解决了一半的问题。

答案 5 :(得分:0)

只是一些一般意见:

  • 请勿使用TIMESTAMP列,因为它会根据INSERT时间自动设置。由于您正在导入数据,这不是您想要的。
  • 如果您使用MySQL DATETIME列类型,则可以在其上使用MySQL Date and Time functions
  • MyISAM不支持FOREIGN KEY约束,并默默忽略它们。
  • 索引,索引,索引。确保将它们放在您将用于查找的列上。但是,如果您的列中包含大量文字,则可能需要在其上使用FULLTEXT searches
  • 如果您计划将其转换为包含INSERTSELECT查询的实时数据库,请考虑将InnoDB用于事务和行级锁定(SELECT ... FOR UPDATE