2012-12-06 55 views
3

我想正确设计我的数据库。也许有人可以帮助我。需要正确的数据库结构来减小大小

我有围绕写入100个键/值每3秒的表的装置。 有人建议将其存储这样的:

^^时间戳key1的^^KEY 2 [...]^^ key150

| 12/06/12 | null | 2243466 | [...]空^

但我认为是完全错误的,而不是动态的。因为我可以有很多空值。 于是,我就尽我所能,并设计它,我怎么在学校学过: http://ondras.zarovi.cz/sql/demo/?keyword=tempidi

这里是我写的每一个值100values内,这意味着这将是始终不变的,并产生大量的时间戳问题数据的。

可能有人给我一个暗示如何降低数据库的大小?我基本上纠正了我的企业风险管理?

+3

您是否关注通过将相同的时间戳写入100行所使用的磁盘空间? –

+0

是的。 我的计算是: 100值* 16bytes * 24(h)* 60(min)* 60(s)* 30(month)= 3.8GB /月 –

+0

无论谁建议像这样存储不应该推荐数据库楷模。 – Kermit

回答

0

如果你要必须在MySQL中实现一个键值存储,那么使它比这更复杂没有任何意义。

create table key_value_store (
    run_time datetime not null, 
    key_name varchar(15) not null, 
    key_value varchar(15) not null, 
    primary key (run_time, key_name) 
); 

如果你的关键字和值两者的平均长度为10字节,你看约86万行,每月2.5GB,你不需要任何连接。如果所有值(列key_value)都是整数或浮点数,则可以更改数据类型并减少一点空间。

一个与SQL实现键值存储的主要问题是,除非所有值都相同的数据类型,你必须使用所有值类似VARCHAR(n)的。你失去了类型安全和声明约束。 (您不能检查key3的值是否在1和15之间,而key7的值是在0和3之间。)


这可行吗?

这种结构(称为“EAV” - 谷歌的那种)是一种众所周知的餐桌设计反模式。问题的一部分是你基本上将列存储为行。 (您在key_value_store.key_name中存储了列名。)如果您有有史以来必须以正常表的格式写出数据,您会发现三件事。

  1. 很难编写查询来输出正确的格式。
  2. 需要永久运行。如果您必须编写数百个列,它可能永远不会完成。
  3. 你会希望你有更快的硬件。很多,很多更快的硬件。

我寻找什么

  • 机遇组键进入逻辑表。这与第一个设计有关,它可能不适用于你。这听起来就像你的应用程序基本上存储了一个日志文件,并且你不知道每次运行哪些键会有值。
  • 减少行数的机会。我会问,“我们可以少写一遍吗?”所以我会考虑每5秒或6秒写入数据库,而不是每3秒写一次,假设这意味着我正在写更少的行。 (真正的目标是更少的行数,而不是更少的写入数量。)
  • 合适的平台。 PostgreSQL 9.2可能是更好的选择。版本9.2具有仅索引扫描,并且它具有实现键值存储的hstore模块。

测试你决定

如果我是你的话,我会在这两个MySQL和PostgreSQL构建这个表之前。我会加载大约一百万行随机数据。然后,我会尝试一些查询和每个报告。 (报告很重要。)衡量绩效。将负载增加到1000万行,重新调整服务器和dbms,然后再次运行相同的查询和报告。再次测量。

重复1亿行。当你有信心时退出。预计这一切需要几天。

+0

优秀的分数,Catcall。 – n8wrl

+0

@YannicDoNotText:2.5GB。我打开了两个电子表格,并将其选中到错误的中间。计算为每分钟20次写入;每写入20 * 100(2000)行;每天2,880,000行;每月8640万行;每行28个字节;每月2419,200,000字节。这是很多行。 –

+0

是的。我知道。但我必须这样做。这是一个有3个月历史数据的监测项目......你认为这有可能吗?有了建议的ERM?第一行和第100列的建议是错误的,不是吗? –

1

我不会太在意数据库的大小。你更大的问题是维护和灵活性。

这是我会做的。首先,定义并填写此表,可能的密钥的设备可以这样写:

tblDataKey 
(
    ID int primary key (auto-increment - not sure how mysql does this) 
    Name varchar(32) 
) 

下一个定义“数据事件”表:

tblEvent 
(
    ID int primary key (auto-inc) 
    TimeStamp 
    ...anything else you need - device ID's? ... 
) 

然后配合按键事件和它们的值:

tblEventData 
{ 
    EventID INT FK-to-tblEvent 
    KeyID INT FK-to-tblDataKey 
    DataValue varchar(???) 
) 

现在需要每然而,许多秒的数据来自于您创建tblEvent与键值单个条目多个条目tblEventData。并非每个事件都需要每个密钥,并且您可以在未来扩展密钥。

这真正的亮点在空间不浪费,你可以很容易地与特定的数据键和值evnets做查询。在这种结构下降的情况下,当你需要制作“交叉表”式的事件和数据项目表时。你必须决定是否有问题。

+0

嗨n8wrl,谢谢你的回答。 我试过了,就像你描述的那样。你可以来看看吗? http://ondras.zarovi.cz/sql/demo/?keyword=tempidi2 –