首页 > 数据库 > MongoDB > 正文

MongoDB范围片键和哈希片键有什么区别?

2024-09-07 00:22:35
字体:
来源:转载
供稿:网友
      这篇文章给大家介绍MongoDB片键,主要介绍范围片键和哈希片键以及两者的不同,对大家学习和理解MongoDB有一定的参考价值,感兴趣的朋友就继续往下看吧。
01 片键
      MongoDB的片键决定了集合中存储的数据在集合中的分布情况,具体的方法是使用片键值的范围来对集合中的数据进行分区。举个例子:
 
      需要注意的是,在一个集合中,被选为片键的这个字段上必须有一个支持片键的索引,或者是必须有一个以这个字段开头的联合索引。通常情况下,我们给字段添加的索引,最常见的是普通索引或者哈希索引,普通的索引字段如果作为片键,那么这个片键我们称为范围片键;哈希索引字段如果作为片键,那么这个片键我们称为哈希片键。下面我们来看二者的不同之处:
 
02 范围片键(递增片键)
      范围片键,顾名思义,就是将数据根据片键划分到连续的范围里面,在这个模型中,那些值"相似"的文档可能位于同一个片中。例如下面这样:
 
      好处:
 
      可以高效的读取连续范围内的目标文档。如果你使用范围查询,则可以比较快速的拿到所有的结果值。因为数据所在的数据chunk比较少。
 
      坏处:
 
      如果我们写入的数据都几种在某一个分片区间,那么读写性能都可能因为片键划分不均匀而降低。(例如下图中,数据的基数大部分在20~maxKey,则大部分都在chunk C的位置,本身分布不均匀),Chunk C的写入压力将会增大。
 
 
 
      在下列场景中,使用范围片键比较合适:
 
      1、数据的基数比较大
 
      2、分片的写入频率比较低(插入较少不容易产生chunk的搬运)
 
      3、非单调变化的分片(如果单调写,则会分到同一个块里面,容易达到chunk割裂的条件,产生chunk的搬运)
 
      如果数据满足上面的三个条件,则我们写入的数据可能是这样的:
 
 
 
      就是比较均匀的写入到了数据块中。
 
03 哈希片键
      哈希片键使用哈希索引在共享集群中对数据进行分区。哈希索引计算单个字段的哈希值作为索引值,该值用作片键(注意,这里并不是字段本身的值,而是hash之后的值)。
 
 
      作为哈希片键的索引字段应该有如下特点:
 
      1、具有大量不同的值
 
      2、哈希索引适合单调变化的字段,例如自增值,时间值等(因为可以将单调的字段通过hash函数映射到不同的块上去,从而分散写入压力,例如下图,虽然数据连续,但是写入了不同的数据块中)
 
      下面是分片创建从无到有的过程举例:
 
1、创建表,只有一个字段name,并插入数据
mongos> use aaa
switched to db aaa
mongos> db.aaa.insert({name:1})
WriteResult({ "nInserted" : 1 })
mongos> db.aaa.insert({name:2})
WriteResult({ "nInserted" : 1 })
mongos> db.aaa.insert({name:3})
WriteResult({ "nInserted" : 1 })
mongos> db.aaa.insert({name:4})
WriteResult({ "nInserted" : 1 })
mongos>
 
2、查看数据
mongos> db.aaa.find()
{ "_id" : ObjectId("5fdb7d54d91f2f9bae3b09a1"), "name" : 1 }
{ "_id" : ObjectId("5fdb7d56d91f2f9bae3b09a2"), "name" : 2 }
{ "_id" : ObjectId("5fdb7d59d91f2f9bae3b09a3"), "name" : 3 }
{ "_id" : ObjectId("5fdb7d5cd91f2f9bae3b09a4"), "name" : 4 }
 
3、允许数据库分片
mongos> sh.enableSharding("aaa")
{
 "ok" : 1,
 "operationTime" : Timestamp(1608220038, 3),
 "$clusterTime" : {
  "clusterTime" : Timestamp(1608220038, 3),
  "signature" : {
   "hash" : BinData(0,"shemm3xvSYrMiy9t7gSYcVtFUuE="),
   "keyId" : NumberLong("6894922308364795934")
  }
 }
}
mongos>
 
4、在name字段创建hash索引
mongos> db.aaa.createIndex({name:"hashed"},{background:true})
{
 "raw" : {
  "sharding_yeyz/127.0.0.1:27018,127.0.0.1:27019,127.0.0.1:27020" : {
   "createdCollectionAutomatically" : false,
   "numIndexesBefore" : 1,
   "numIndexesAfter" : 2,
   "ok" : 1
  }
 },
 "ok" : 1,
 "operationTime" : Timestamp(1608220115, 3),
 "$clusterTime" : {
  "clusterTime" : Timestamp(1608220115, 3),
  "signature" : {
   "hash" : BinData(0,"S3Wz9G26eJyOcwa1OLS6TVYu6SE="),
   "keyId" : NumberLong("6894922308364795934")
  }
 }
}
 
5、以name字段作为片键创建哈希分片
mongos> sh.shardCollection("aaa.aaa",{name:"hashed"})
{
 "collectionsharded" : "aaa.aaa",
 "collectionUUID" : UUID("20a3895e-d821-43ae-9d28-305e6ae03bbc"),
 "ok" : 1,
 "operationTime" : Timestamp(1608220238, 10),
 "$clusterTime" : {
  "clusterTime" : Timestamp(1608220238, 10),
  "signature" : {
   "hash" : BinData(0,"qeQlD3jsSvRZkyamEa2hjbezEdM="),
   "keyId" : NumberLong("6894922308364795934")
  }
 }
}

(编辑:武林网)

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表