CouchDB的推荐文档结构

maj*_*oat 7 couchdb data-modeling

我们目前正在考虑将Postgres更改为CouchDB以用于使用情况监控应用程序.一些数字:

大约2000个连接,每5分钟轮询一次,每天大约600,000个新行.在Postgres中,我们存储这些数据,按日分区:

t_usage {service_id,timestamp,data_in,data_out}
t_usage_20100101继承t_usage.
t_usage_20100102继承了t_usage.等等

我们使用乐观存储过程来编写数据,该过程假设分区存在并在必要时创建它.我们可以很快插入.

为了读取数据,我们的用例按重要性和当前性能顺序排列:
*单一服务,单日使用:良好的性能
*多种服务,月使用:性能不佳
*单一服务,月使用:性能不佳
*多种服务,多个月:性能非常差
*多项服务,单日:良好的表现

这是有道理的,因为分区已经优化了几天,这是迄今为止我们最重要的用例.但是,我们正在研究改进二级要求的方法.

我们经常需要按小时参数化查询,例如,仅在上午8点到下午6点之间给出结果,因此汇总表的用途有限.(这些参数的变化频率足以创建多个数据汇总表,这是令人望而却步的).

在此背景下,第一个问题是:CouchDB是否适合这些数据?如果是,在给定上述用例的情况下,您将如何在CouchDB文档中对数据进行最佳建模?到目前为止,我已经整理了一些选项,我们正在进行基准测试(_id,_rev除外):

每天每个连接一个文档

{
  service_id:555
  day:20100101
  usage: {1265248762: {in:584,out:11342}, 1265249062: {in:94,out:1242}}
}
Run Code Online (Sandbox Code Playgroud)

每月大约有60,000份新文件.大多数新数据都是对现有文档的更新,而不是新文档.

(这里,使用中的对象键入轮询的时间戳,以及字节输入和字节输出的值).

每月连接一个文档

{
  service_id:555
  month:201001
  usage: {1265248762: {in:584,out:11342}, 1265249062: {in:94,out:1242}}
}
Run Code Online (Sandbox Code Playgroud)

每月大约2,000份新文件.适度更新现有文档.

每行收集一份文档

{
  service_id:555
  timestamp:1265248762
  in:584
  out:11342
}
{
  service_id:555
  timestamp:1265249062
  in:94
  out:1242
}
Run Code Online (Sandbox Code Playgroud)

每月大约15,000,000份新文件.所有数据都是新文档的插入.插入速度更快,但我对数百万份文档在一年或两年后的效率有疑问.文件IO似乎太高了(虽然我是第一个承认我不完全理解它的机制).

我试图以面向文档的方式解决这个问题,虽然打破RDMS的习惯很困难:)事实上,你只能对视图进行最低限度的参数设置让我有点担忧.那就是说,上面哪一个最合适呢?是否有其他格式我没有考虑哪种格式会更好?

提前致谢,

杰米.

Wil*_*ung 10

我不认为这是一个可怕的想法.

让我们考虑一下你的连接/月场景.

鉴于一个条目的长度约为40(这是慷慨的),并且每月收到约8,200个条目,您的最终文档大小将在月末达到约350K.

这意味着,全力以赴,你每5分钟就会阅读和写入2000个350K文件.

I/O方面,考虑到读取和写入,这个小于6 MB/s,平均为5米时间窗口.这在今天的低端硬件中都很好.

但是,还有另一个问题.当您存储该文档时,Couch将评估其内容以构建其视图,因此Couch将解析350K文档.我担心(最后检查,但已经过了一段时间)我不相信Couch在CPU核心上的扩展性很好,所以这可以轻松地固定Couch将使用的单CPU核心.我希望Couch能够读取,解析和处理2 MB/s,但我坦率地说不知道.有了它的所有好处,erlang并不是直线计算机语言中最好的运输方式.

最后一个问题是跟上数据库的步伐.这将在月底每5分钟写700 MB.使用Couchs架构(仅附加),您将每5分钟写入700MB数据,每小时8.1GB,24小时后201GB.

在压缩数据库之后,它会压缩到700MB(一个月),但在此过程中,该文件将变得越来越大,并且很快.

在检索方面,这些大型文件不会吓到我.加载一个350K的JSON文档,是的它很大,但它不是那么大,不是现代硬件.公告板上有更大的头像.因此,我认为,您想要做的关于一个月内连接活动的任何事情都会非常快.在连接中,显然你抓得越多,它就会越贵(所有2000个连接都是700MB).700MB是一个真正影响的实数.此外,您的流程需要积极地丢弃您不关心的数据,这样它就可以丢弃箔条(除非您想在报告过程中加载700MB的堆).

鉴于这些数字,连接/日可能是更好的选择,因为您可以更好地控制粒度.但是,坦率地说,我会选择最粗糙的文档,因为我认为这样可以从数据库中获得最大的价值,仅仅是因为今天所有的头部搜索和盘片旋转都会导致很多I/O性能下降,很多磁盘流数据非常好.较大的文件(假设数据很好,因为Couch经常被压缩,这不应该是一个问题),而不是寻求.与磁盘相比,在内存中寻找是"免费的".

一定要在我们的硬件上运行您自己的测试,但要牢记所有这些考虑因素.

编辑:

经过更多实验......

几个有趣的观察.

在导入大型文档期间,CPU对I/O速度同样重要.这是因为通过将JSON转换为内部模型以供视图使用而消耗的编组和CPU消耗量.通过使用大型(350k)文档,我的CPU几乎达到了最大限度(350%).相比之下,对于较小的文档,它们在200%时嗡嗡作响,尽管总的来说,它是相同的信息,只是以不同的方式组合.

对于I/O,在350K文档中,我绘制的是11MB /秒,但是对于较小的文档,它只有8MB /秒.

压缩似乎几乎是I/O绑定.我的I/O潜力很难得到很好的数据.缓存文件的副本推送40 + MB /秒.压缩速度约为8MB /秒.但这与原始负载一致(假设沙发正按消息移动消息).CPU处于较低的状态,因为它处理的处理较少(它不解释JSON有效负载或重建视图),而且它只是一个CPU来完成工作.

最后,为了阅读,我试图转储整个数据库.一个CPU挂了这个,我的I/O很低.我确保CouchDB文件实际上没有被缓存,我的机器有很多内存,所以很多东西都被缓存了.通过_all_docs的原始转储只有大约1 MB /秒.这几乎都是寻求和旋转延迟比其他任何东西.当我使用大型文档执行此操作时,I/O达到3 MB /秒,这只是显示了流媒体效果,我提到了更大的文档的好处.

值得注意的是,Couch网站上有一些技术可以提高我未遵循的性能.值得注意的是,我使用的是随机ID.最后,这并不是衡量Couch性能的指标,而是衡量负载最终的位置.我认为大而小的文档差异很有趣.

最后,最终的性能并不像简单地为您的硬件应用程序执行得那么重要.正如你所提到的,你正在做自己的测试,而这才是真正重要的.