这个架构有什么好的mongodb分片键?

Chr*_*tta 3 sharding mongodb

架构

{
        "_id" : ObjectId("5069d68700a2934015000000"),
        "port_name" : "CL1-A",
        "metric" : 340,
        "port_number" : "0",
        "datetime" : ISODate("2012-09-30T13:44:00Z"),
        "array_serial" : "12345"
}
Run Code Online (Sandbox Code Playgroud)

每个阵列有128个端口,每个文档是该指标的一分钟数据.似乎array_serial对于分片键不是一个好选择,因为基数较低,也就是说,串行的所有数据12345都必须保留在同一个分片上而不能分成块,对吗?

这似乎port_number会允许适度的基数,但是它会使查询隔离失败,因为同一阵列上的多个端口的单个查询将跨越多个分片.我预计用户不需要一次查询超过4-8个端口.

答案是一个组合吗?我应该使用一段日期时间,如月份还是周?

Mar*_*ick 7

关于阵列串行,是的,这是正确的.

如果你选择"port_number",它将具有足够高的基数,并且意味着所有具有相同"port_number"的文档将驻留在同一个块中,但如果查询到达一系列端口,那么它将达到多个碎片.

正如您所猜测的那样,选择正确的分片键非常重要而且很难."完美"分片键满足三个互斥目标:

  • 写入应均匀分布在分片上
  • 单个文档的查询应均匀分布在分片上
  • 范围查询和排序应该是高效的,这意味着序列中的元素应该都在同一个分片上.

避免顺序分片键的原因之一是它会在插入上创建热点:在任何给定时间,单个分片将占用所有插入负载(它有利于查询隔离但最终不是性能 - 因此_id和"datetime" "不是很好的选择." 我可能会去复合分片键.Google集团就此主题进行了一些很好的讨论:

如果您选择类似{array_serial:1,datetime:1}的内容,则"array_serial"的数据将根据需要分解为多个块(基于日期时间)并分布在服务器上.使用完整的"datatime"值.

"array_serial"是如何决定的?价值范围是多少?我假设port_name更改为port_number更改?

鉴于你所说的,我可能会去{port_number:1,datetime:1},它并不完美,但它并不坏.

这是你最好的选择吗?这实际上取决于使用信息.

  • 您最常见的查询是什么?

如果您主要是在特定端口号范围内对特定名称进行查询,那么这可能是您的最佳选择.

另一方面,如果您将主要根据日期时间而不管端口号执行所有"名称"的查询,那么您每次都会进行分散/收集查询,这将降低群集的整体性能.

另外,问问自己

  • 单个碎片可以处理所有插入物吗?

  • 范围查询性能对您来说真的很重要吗?

基于你的问题,我猜你已经阅读了关于选择分片键的链接:)

以下是一些关于选择可能对您有用的好的分片键的进一步讨论: