Database MongoDb-用于分片的重复索引字段?

Database MongoDb-用于分片的重复索引字段?,database,mongodb,performance,indexing,sharding,Database,Mongodb,Performance,Indexing,Sharding,我想构建一个集群来存储日志数据。每个文档都有几个字段,但这些是关键字段: 用户id(中等基数) 标识符(它具有极高的基数,但不能保证在用户之间是唯一的,例如,它可以是UPC) 通道(低基数) 时间戳 该集合预计将有超过10亿个文档,因此切分和性能在这里非常重要 现在几乎所有对集合的高频查询都将包含user\u id,因为日志在UI中以唯一方式显示给每个用户。大多数查询将在用户id+标识符上进行。有些查询是有时间限制的。有些查询也使用频道,但不是全部user\u id是一个单调递增的字段 我想

我想构建一个集群来存储日志数据。每个文档都有几个字段,但这些是关键字段:

  • 用户id(中等基数)
  • 标识符(它具有极高的基数,但不能保证在用户之间是唯一的,例如,它可以是UPC)
  • 通道(低基数)
  • 时间戳
该集合预计将有超过10亿个文档,因此切分和性能在这里非常重要

现在几乎所有对集合的高频查询都将包含
user\u id
,因为日志在UI中以唯一方式显示给每个用户。大多数查询将在
用户id
+
标识符上进行。有些查询是有时间限制的。有些查询也使用
频道
,但不是全部
user\u id
是一个单调递增的字段

我想在
散列(用户id)
上进行切分。一个理想的索引是
{“user_id”:1,“identifier”:1,“timestamp”:1}
,所以我做了这个。我尝试在
散列(user\u id)
上进行切分,但在这种情况下不起作用,我意识到
user\u id
必须是相同的类型。但是,由于不允许使用带有散列的复合键,因此也不可能将索引设为
{“user_id”:“hash”,“identifier”:1,“timestamp”:1}

我最好的选择是什么

  • 创建一个只使用
    散列(user\u id)
    的索引,这样我就可以对它进行切分,然后创建另一个带有
    {“user\u id”:1,“identifier”:1,“timestamp”:1}
    ?我会在这里招致存储罚款
  • 不要散列
    user\u id
    ,即使它是单调递增的,而是在
    {“user\u id”:1,“identifier”:1}
    ?我不确定与在
    hash(user\u id)
  • 还有别的选择吗

请注意,MongoDB 4.4允许使用单个散列字段的复合索引:

如果您不能轻松升级到4.4,考虑到这里的存储压力很高,文档数量很多,而且大多数查询都包含
user\u id
identifier
,那么在
{“user\u id”:1,“identifier”:1}
上分片听起来是您在这里的最佳选择。它将允许这些查询快速进行,而您的其他查询需要搜索每个用户的所有标识符或基于时间的查询

我不确定是否有比MongoDB 4.4版本更好的解决方案

创建一个仅使用散列(user_id)的索引,这样我就可以对其进行切分并 然后是另一个带有{“user_id”:1,“identifier”:1,“timestamp”的索引: 1 }? 我会在这里招致存储罚款

您只能有一个分片键(这需要是一个索引字段、单个字段或复合字段)。对于shard键的散列索引字段,从MongoDB v4.2开始,它只能是单个字段索引

使用分片键(或复合分片键的前缀)查询具有条件的分片集合将是一个目标查询。
mongos
将仅访问所需的碎片。因此,它将是一个高效的查询

在查询条件中不使用分片键进行查询只会导致分散-聚集操作-将访问集群中的所有分片。即使查询的字段上有索引,也仍然是分散操作

因此,选择分片键可能是分片集群设置中最重要的部分

不要散列用户id,即使它是单调递增的 而是在{“user_id”:1,“identifier”:1}上切分?我不确定 与简单的分片相比,这里有一些缺点 散列(用户id)

您的查询需求应该驱动您的切分键选择(我已经在上面提到了切分键)


MongoDB v4.4(最新版本)允许。

这是一个很好的时机,似乎4.4版完美地解决了我的用例问题——谢谢!