我的问题有2个子问题:
让我们假设每秒接收数据的情况,该数据表示为一组键/值元组。每个值基本上都是64位计数器。我需要将它保存到数据库中。值的数量是几千。在这些数千只中,只有1%具有实际数据,而其他数据为空(稀疏填充集)。制作几千列的表是否有意义?或者只是存储为" id,时间戳,键,值"?
如果对问题1的回答是"应该使用数千个列",来自mysql / postgres系列的da?
此案例的读取模式主要是图表,因此select将是基于时间戳的一堆数据。因此,它是统一的1 /秒写入和偶尔读取日期/时间范围内的所有数据或数据。
奖金问题,可以使用哪种模式在NoSQL数据库中存储此类数据?例如,在MongoDB中,可以使用包含仅占整个集合的1%的文档的统计集合。在这种情况下,如何使用read / map / reduce?如何读取数据与mysql / postgres相比?
编辑:我的用例与NewRelic服务非常相似,但是我没有大量的小数据集,而是拥有更大的数据集(稀疏地填充了更大的数据集)但不常用(和更少的用户)
答案 0 :(得分:1)
PostgreSQL将空列存储为位图,但每行的开销很大。让我们计算两种存储方案的存储效率:
Average row length for wide table with thousands of columns:
23 bytes row header + 1000*1bit + average 2 bytes of alignment + 4 bytes id
+ 8 bytes timestamp + 10*8 bytes values = 242 bytes
Average number of bytes for storing each value separately:
10 values * (23 bytes row header + 1 byte alignment + 4 bytes id
+ 8 bytes timestamp + 4 bytes key + 8 bytes value) = 480 bytes
所以千列的效率大约是按键分割出来的两倍。分开存储密钥效率更高的交叉点是about 0.45%。
然而,这种方法的规模不会很大。 PostgreSQL中的最大列数限制为1600.要进一步扩展它,可以将值垂直拆分为多个表。这也会有一些问题需要查询,因为结果集也不能大于1600。
另一种选择是将键值对编码为数组。在这种情况下,表的结构将是(id serial,ts timestamptz,keys int2 [],values int8 [])。相同1000个属性的存储开销,1%填充因子将是:
23 bytes row header + 1 byte alignment + 4 bytes id + 8 bytes timestamp
+ 20 bytes array header + 10*2 byte values + 20 bytes array header
+ 10*8 byte values = 176 bytes per entry
然而,在这种情况下,查询奇异值需要更多的基础设施。
如果需要更高的存储效率或灵活性,可以添加自定义数据类型。
我知道传感器数据的大数列模式在许多PostgreSQL安装中成功使用。至于数据库选择,我可能有点偏颇,但我会建议PostgreSQL,因为你会有更好的工具,如数组,谓词索引和自定义数据类型,以重新安排数据存储,以提高效率。要记住的最重要的事情是从get go开始使用分区。
答案 1 :(得分:0)
当您需要设计具有数千个相同数据类型列的表的唯一情况是,您的数据库具有需要具有这些列的外键重量的其他表。除了拥有数千列之外,充其量是无法管理的。
您还可以使用jdbm2等持久性地图存储引擎。它专为像您一样的类似用例而设计。