服务器之家:专注于服务器技术及软件下载分享
分类导航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|数据库技术|

服务器之家 - 数据库 - MongoDB - 详解MongoDB范围片键和哈希片键

详解MongoDB范围片键和哈希片键

2021-05-09 20:56AsiaYe MongoDB

这篇文章主要介绍了MongoDB范围片键和哈希片键的相关资料,帮助大家更好的理解和学习使用MongoDB,感兴趣的朋友可以了解下

01 片键

    mongodb的片键决定了集合中存储的数据在集合中的分布情况,具体的方法是使用片键值的范围来对集合中的数据进行分区。举个例子:

假如我们以年龄age来作为片键,那么age的范围理论上是0~80,此时,mongodb会为我们定义age的四个范围区间,他们分别是:0~20,20~40,40~60,60~80,每个范围都是一个chunk,这样我们写入数据之后,数据里面的数据块就有:

chunk1:  age  0~20

chunk2:  age  20~40   

chunk3:age  40~60

chunk4:age  60~80

需要注意的是,在一个集合中,被选为片键的这个字段上必须有一个支持片键的索引,或者是必须有一个以这个字段开头的联合索引。

通常情况下,我们给字段添加的索引,最常见的是普通索引或者哈希索引,

普通的索引字段如果作为片键,那么这个片键我们称为范围片键;

哈希索引字段如果作为片键,那么这个片键我们称为哈希片键。

下面我们来看二者的不同之处:

02 范围片键(递增片键)

范围片键,顾名思义,就是将数据根据片键划分到连续的范围里面,在这个模型中,那些值"相似"的文档可能位于同一个片中。例如下面这样:

详解MongoDB范围片键和哈希片键

这中分片方式是mongodb默认的分片方式,它有好处也有坏处。

好处:

    可以高效的读取连续范围内的目标文档。如果你使用范围查询,则可以比较快速的拿到所有的结果值。因为数据所在的数据chunk比较少。

坏处:

    如果我们写入的数据都几种在某一个分片区间,那么读写性能都可能因为片键划分不均匀而降低。(例如下图中,数据的基数大部分在20~maxkey,则大部分都在chunk c的位置,本身分布不均匀),chunk c的写入压力将会增大。

详解MongoDB范围片键和哈希片键

在下列场景中,使用范围片键比较合适:

1、数据的基数比较大

2、分片的写入频率比较低(插入较少不容易产生chunk的搬运)

3、非单调变化的分片(如果单调写,则会分到同一个块里面,容易达到chunk割裂的条件,产生chunk的搬运)

如果数据满足上面的三个条件,则我们写入的数据可能是这样的:

详解MongoDB范围片键和哈希片键

就是比较均匀的写入到了数据块中。

03 哈希片键

    哈希片键使用哈希索引在共享集群中对数据进行分区。哈希索引计算单个字段的哈希值作为索引值,该值用作片键(注意,这里并不是字段本身的值,而是hash之后的值)。

    使用哈希索引,我们写入数据之后,对应写入数据块的图示可能如下:

详解MongoDB范围片键和哈希片键

从图中我们看出来,虽然我们输入的x值比较接近,分别是25、26、27,但是,经过hash函数之后,他们所在的数据块序号可能差距很远。

哈希分片在分片集群中提供了更均匀的数据分布,集合中那些具有近似值的文档,可能会被分到不同的块上,mongos更有可能执行广播操作来完成给定的范围查询。

哈希值得计算,是由mongodb来负责的,不是应用程序负责的

作为哈希片键的索引字段应该有如下特点:

1、具有大量不同的值

2、哈希索引适合单调变化的字段,例如自增值,时间值等(因为可以将单调的字段通过hash函数映射到不同的块上去,从而分散写入压力,例如下图,虽然数据连续,但是写入了不同的数据块中)

详解MongoDB范围片键和哈希片键

它的缺点也比较明显,当我们查询某个范围的值的时候,hash索引会查找更多的数据分片,并将最终的结果汇总起来交给我们。

在实际生产环境中,我们需要结合自己的需求来确定使用哪种类型的片键,再次强调,在设定某个字段作为片键之前,需要先在当前字段创建对应类型的索引,或者创建一个以当前字段开头的联合索引。否则设定片键的语句会报错。

下面是分片创建从无到有的过程举例:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
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")
  }
 }
}
 
6、查看分片信息
mongos> db.printshardingstatus()
--- sharding status ---
 sharding version: {
 "_id" : 1,
 "mincompatibleversion" : 5,
 "currentversion" : 6,
 "clusterid" : objectid("5fafaf4f5785d9965548f687")
 }
 shards:
 { "_id" : "sharding_yeyz", "host" : "sharding_yeyz/127.0.0.1:27018,127.0.0.1:27019,127.0.0.1:27020", "state" : 1 }
 { "_id" : "sharding_yeyz1", "host" : "sharding_yeyz1/127.0.0.1:27024,127.0.0.1:27025,127.0.0.1:27026", "state" : 1 }
 active mongoses:
 "4.0.6" : 1
 autosplit:
 currently enabled: yes
 balancer:
 currently enabled: yes
 currently running: no
 failed balancer rounds in last 5 attempts: 2
 last reported error: could not find host matching read preference { mode: "primary" } for set sharding_yeyz
 time of reported error: wed nov 18 2020 17:08:14 gmt+0800 (cst)
 migration results for the last 24 hours:
  no recent migrations
 databases:
 { "_id" : "aaa", "primary" : "sharding_yeyz", "partitioned" : true, "version" : { "uuid" : uuid("26e55931-d1c1-4dc5-8a03-b5b0e70f6f43"), "lastmod" : 1 } }
  aaa.aaa
   shard key: { "name" : "hashed" }
   unique: false
   balancing: true
   chunks:
    sharding_yeyz 1
   { "name" : { "$minkey" : 1 } } -->> { "name" : { "$maxkey" : 1 } } on : sharding_yeyz timestamp(1, 0)

以上就是详解mongodb范围片键和哈希片键的详细内容,更多关于mongodb范围片键和哈希片键的资料请关注服务器之家其它相关文章!

原文链接:https://cloud.tencent.com/developer/article/1766065

延伸 · 阅读

精彩推荐
  • MongoDBMongoDB的索引

    MongoDB的索引

    数据库中的索引就是用来提高查询操作的性能,但是会影响插入、更新和删除的效率,因为数据库不仅要执行这些操作,还要负责索引的更新 ...

    MongoDB教程网2532020-05-12
  • MongoDB在mac系统下安装与配置mongoDB数据库

    在mac系统下安装与配置mongoDB数据库

    这篇文章主要介绍了在mac系统下安装与配置mongoDB数据库的操作步骤,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪...

    CXYhh1219312021-11-14
  • MongoDBMongoDB系列教程(五):mongo语法和mysql语法对比学习

    MongoDB系列教程(五):mongo语法和mysql语法对比学习

    这篇文章主要介绍了MongoDB系列教程(五):mongo语法和mysql语法对比学习,本文对熟悉Mysql数据库的同学来说帮助很大,用对比的方式可以快速学习到MongoDB的命...

    MongoDB教程网3252020-05-01
  • MongoDBMongodb索引的优化

    Mongodb索引的优化

    MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。接下来通过本文给大家介绍Mongodb索引的优化,本文介绍的非常详细,具有参考借鉴价值,感...

    MRR3252020-05-05
  • MongoDBMongoDB查询之高级操作详解(多条件查询、正则匹配查询等)

    MongoDB查询之高级操作详解(多条件查询、正则匹配查询等)

    这篇文章主要给大家介绍了关于MongoDB查询之高级操作(多条件查询、正则匹配查询等)的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者...

    w田翔3872020-12-19
  • MongoDBMongoDB多条件模糊查询示例代码

    MongoDB多条件模糊查询示例代码

    这篇文章主要给大家介绍了关于MongoDB多条件模糊查询的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用MongoDB具有一定的参考学习价值...

    浅夏晴空5902020-05-25
  • MongoDBmongodb数据库基础知识之连表查询

    mongodb数据库基础知识之连表查询

    这篇文章主要给大家介绍了关于mongodb数据库基础知识之连表查询的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用mongodb具有一定的参...

    ZJW02155642020-05-22
  • MongoDBWindows下MongoDB配置用户权限实例

    Windows下MongoDB配置用户权限实例

    这篇文章主要介绍了Windows下MongoDB配置用户权限实例,本文实现需要输入用户名、密码才可以访问MongoDB数据库,需要的朋友可以参考下 ...

    MongoDB教程网3082020-04-29