- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章详解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默认的分片方式,它有好处也有坏处.
好处:
可以高效的读取连续范围内的目标文档。如果你使用范围查询,则可以比较快速的拿到所有的结果值。因为数据所在的数据chunk比较少.
坏处:
如果我们写入的数据都几种在某一个分片区间,那么读写性能都可能因为片键划分不均匀而降低。(例如下图中,数据的基数大部分在20~maxkey,则大部分都在chunk c的位置,本身分布不均匀),chunk c的写入压力将会增大.
在下列场景中,使用范围片键比较合适:
1、数据的基数比较大 。
2、分片的写入频率比较低(插入较少不容易产生chunk的搬运) 。
3、非单调变化的分片(如果单调写,则会分到同一个块里面,容易达到chunk割裂的条件,产生chunk的搬运) 。
如果数据满足上面的三个条件,则我们写入的数据可能是这样的:
就是比较均匀的写入到了数据块中.
03 哈希片键 。
哈希片键使用哈希索引在共享集群中对数据进行分区。哈希索引计算单个字段的哈希值作为索引值,该值用作片键(注意,这里并不是字段本身的值,而是hash之后的值).
使用哈希索引,我们写入数据之后,对应写入数据块的图示可能如下:
从图中我们看出来,虽然我们输入的x值比较接近,分别是25、26、27,但是,经过hash函数之后,他们所在的数据块序号可能差距很远.
哈希分片在分片集群中提供了更均匀的数据分布,集合中那些具有近似值的文档,可能会被分到不同的块上,mongos更有可能执行广播操作来完成给定的范围查询.
哈希值得计算,是由mongodb来负责的,不是应用程序负责的 。
作为哈希片键的索引字段应该有如下特点:
1、具有大量不同的值 。
2、哈希索引适合单调变化的字段,例如自增值,时间值等(因为可以将单调的字段通过hash函数映射到不同的块上去,从而分散写入压力,例如下图,虽然数据连续,但是写入了不同的数据块中) 。
它的缺点也比较明显,当我们查询某个范围的值的时候,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 。
最后此篇关于详解MongoDB范围片键和哈希片键的文章就讲到这里了,如果你想了解更多关于详解MongoDB范围片键和哈希片键的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在尝试 grep conf 文件中所有不以 开头的有效行 哈希(或) 任意数量的空格(0 个或多个)和一个散列 下面的正则表达式似乎不起作用。 grep ^[^[[:blank:]]*#] /op
我正在使用哈希通过 URL 发送 protected 电子邮件以激活帐户 Hash::make($data["email"]); 但是哈希结果是 %242y%2410%24xaiB/eO6knk8sL
我是 Perl 的新手,正在尝试从文本文件创建散列。我有一个代码外部的文本文件,旨在供其他人编辑。前提是他们应该熟悉 Perl 并且知道在哪里编辑。文本文件本质上包含几个散列的散列,具有正确的语法、缩
我一直在阅读 perl 文档,但我不太了解哈希。我正在尝试查找哈希键是否存在,如果存在,则比较其值。让我感到困惑的是,我的搜索结果表明您可以通过 if (exists $files{$key}) 找到
我遇到了数字对映射到其他数字对的问题。例如,(1,2)->(12,97)。有些对可能映射到多个其他对,所以我真正需要的是将一对映射到列表列表的能力,例如 (1,2)->((12,97),(4,1))。
我见过的所有 Mustache 文档和示例都展示了如何使用散列来填充模板。我有兴趣去另一个方向。 EG,如果我有这个: Hello {{name}} mustache 能否生成这个(伪代码): tag
我正在尝试使用此公式创建密码摘要以获取以下变量,但我的代码不匹配。不确定我做错了什么,但当我需要帮助时我会承认。希望有人在那里可以提供帮助。 文档中的公式:Base64(SHA1(NONCE + TI
我希望遍历我传递给定路径的这些数据结构(基本上是目录结构)。 目标是列出根/基本路径,然后列出所有子 path s 如果它们存在并且对于每个子 path存在,列出 file从那个子路径。 我知道这可能
我希望有一个包含对子函数的引用的散列,我可以在其中根据用户定义的变量调用这些函数,我将尝试给出我正在尝试做的事情的简化示例。 my %colors = ( vim => setup_vim()
我注意到,在使用 vim 将它们复制粘贴到文件中后尝试生成一些散列时,散列不是它应该的样子。打开和写出文件时相同。与 nano 的行为相同,所以一定有我遗漏的地方。 $ echo -n "foo"
数组和散列作为状态变量存在限制。从 Perl 5.10 开始,我们无法在列表上下文中初始化它们: 所以 state @array = qw(a b c); #Error! 为什么会这样?为什么这是不允
在端口 80 上使用 varnish 5.1 的多网站设置中,我不想缓存所有域。 这在 vcl_recv 中很容易完成。 if ( req.http.Host == "cache.this.domai
基本上,缓存破坏文件上的哈希不会更新。 class S3PipelineStorage(PipelineMixin, CachedFilesMixin, S3BotoStorage): pa
eclipse dart插件在“变量” View 中显示如下内容: 在“值”列中可见的“id”是什么意思? “id”是唯一的吗?在调试期间,如何确定两个实例是否相同?我是否需要在所有类中重写toStr
如何将Powershell中的命令行参数读入数组?就像是 myprogram -file file1 -file file2 -file file3 然后我有一个数组 [file1,file2,fil
我正尝试在 coldfusion 中为我们的安全支付网关创建哈希密码以接受交易。 很遗憾,支付网关拒绝接受我生成的哈希值。 表单发送交易的所有元素,并发送基于五个不同字段生成的哈希值。 在 PHP 中
例如,我有一个包含 5 个元素的哈希: my_hash = {a: 'qwe', b: 'zcx', c: 'dss', d: 'ccc', e: 'www' } 我的目标是每次循环哈希时都返回,但没
我在这里看到了令人作呕的类似问题,但没有一个能具体回答我自己的问题。 我正在尝试以编程方式创建哈希的哈希。我的问题代码如下: my %this_hash = (); if ($user_hash{$u
我正尝试在 coldfusion 中为我们的安全支付网关创建哈希密码以接受交易。 很遗憾,支付网关拒绝接受我生成的哈希值。 表单发送交易的所有元素,并发送基于五个不同字段生成的哈希值。 在 PHP 中
这个问题已经有答案了: Java - how to convert letters in a string to a number? (9 个回答) 已关闭 7 年前。 我需要一种简短的方法将字符串转
我是一名优秀的程序员,十分优秀!