MongoDB 7.0 分片键分析助手--analyzeShardKey()

发布时间 2023-12-16 13:48:58作者: abce

分片键是群集的关键组成部分,因为它决定了数据在分片中的分布。

 

分片集群的大部分问题都与错误的分片键选择有关;对于一个好的分片键,必须注意以下几点:

·分片键的 cardinality

·分片键值出现的频率

·潜在分片键值是否单调增长

·分片查询模式

在老版本中,分片键是不可变的,但现在(+4.4),提供了新的功能来改进甚至改变你的分片键。比如重定义或重新分片。仍然需要手动查询你的集合来回答上面的问题,比如你的键是否具有良好的 cardinality 和频率等等。

MongoDB 7.0 增加了两个新方法,它们返回的指标对评估现有或潜在的新分区键非常有用。这两种方法是:

db.collection.analyzeShardKey()


db.adminCommand(
   {
     analyzeShardKey: <string>,
     key: <shardKey>,
     keyCharacteristics: <bool>,
     readWriteDistribution: <bool>,
     sampleRate: <double>,
     sampleSize: <int>
   }
 )

输出结果会提供三个包含统计数据的文档:

·keyCharacteristics:提供有关分片键的 cardinality、频率和单调性指标。

·readDistribution/writeDistribution:提供有关查询路由模式和分片键范围热点的指标。

analyzeShardKey计算用于评估未分片或分片集合的分片键的统计信息,基于抽样查询。可以使用 configureQueryAnalyzer 配置集合上的查询采样比例。

analyzeShardKey 不会阻塞集合上的读写操作。

 

analyzeShardKey 的语法:

db.adminCommand(
   {
     analyzeShardKey: <string>,--集合的命名空间,必须指定,没有默认值
     key: <shardKey>,--要分析的分片键,可以是已经做了分片,或者为分片的;必选参数
     keyCharacteristics: <bool>,--是否估算分片键的统计信息;可选项
     readWriteDistribution: <bool>,--是否估算读写分布的统计信息;可选项
     sampleRate: <double>,--采样比例;可选项必须;必须大于0,最大可以等于1;如果设置了该值,就不可以设置sampleSize
     sampleSize: <int> --采样数量;可选参数
   }
 )

analyzeShardKey 会根据运行时指定的 keyCharacteristic 和 readWriteDistribution 值返回不同的指标。

下面,以两个候选分片键为例说明 analyzeShardKey()。

 

由于该集合尚未分片,我们设置了 readWriteDistribution: false。可以使用新方法来帮助你评估一个已使用的分片键或一个未来的分片键,如下所示:

db.adminCommand({analyzeShardKey: "percona.employee", key: {badgeId: "hashed"},readWriteDistribution: false })
{
  keyCharacteristics: {
    numDocsTotal: Long("13591000"),
    avgDocSizeBytes: Long("207"),
    numDocsSampled: Long("10000000"),
    isUnique: false,
    numDistinctValues: Long("9988503"),
    mostCommonValues: [
      {
        value: { badgeId: Long("8472676555298607") },
        frequency: Long("3")
      },
      {
        value: { badgeId: Long("4284333888163027") },
        frequency: Long("3")
      },
      {
        value: { badgeId: Long("3463302535508078") },
        frequency: Long("3")
      },
      {
        value: { badgeId: Long("5807207987841736") },
        frequency: Long("3")
      },
      {
        value: { badgeId: Long("88360867693259") },
        frequency: Long("3")
      }
    ],
    monotonicity: { recordIdCorrelationCoefficient: 0, type: 'not monotonic' }
  },
  ok: 1,
  '$clusterTime': {
    clusterTime: Timestamp({ t: 1696960527, i: 1 }),
    signature: {
      hash: Binary.createFromBase64("i+DjCSA7WpV3KJAT5HwXhTLb7uw=", 0),
      keyId: Long("7288022888098037764")
    }
  },
  operationTime: Timestamp({ t: 1696960524, i: 1 })
}

第二个

> db.adminCommand({analyzeShardKey: "percona.employee", key: {created: 1},readWriteDistribution: false })
{
  keyCharacteristics: {
    numDocsTotal: Long("13591000"),
    avgDocSizeBytes: Long("207"),
    numDocsSampled: Long("9998918"),
    isUnique: false,
    numDistinctValues: Long("955449"),
    mostCommonValues: [
      {
        value: { created: ISODate("2023-10-10T17:01:02.732Z") },
        frequency: Long("21")
      },
      {
        value: { created: ISODate("2023-10-10T17:14:32.273Z") },
        frequency: Long("20")
      },
      {
        value: { created: ISODate("2023-10-10T17:01:16.426Z") },
        frequency: Long("20")
      },
      {
        value: { created: ISODate("2023-10-10T17:01:03.824Z") },
        frequency: Long("20")
      },
      {
        value: { created: ISODate("2023-10-10T17:02:06.022Z") },
        frequency: Long("20")
      }
    ],
    monotonicity: { recordIdCorrelationCoefficient: 0.9999999911, type: 'monotonic' }
  },
  ok: 1,
  '$clusterTime': {
    clusterTime: Timestamp({ t: 1696960030, i: 1 }),
    signature: {
      hash: Binary.createFromBase64("LHsIUx9Au7axEpq7eLYcTa0mkmM=", 0),
      keyId: Long("7288022888098037764")
    }
  },
  operationTime: Timestamp({ t: 1696960024, i: 1 })
}

根据这个输出结果,就可以通过检查文档总数除以不同值的数量来了解你的关键字是否具有高过滤性。

mostCommonValues 字段增加了对某个值频率的了解;如果频率很高,则可能预示着未来可能会出现 jumbo 数据,因为这些值经常重复,从而增加了数据块,进而变得不可分割。

analyzeShardKey() 使用查询采样配置来计算指标;作为新功能的一部分,你可以通过 configureQueryAnalyzer() 来配置查询采样。