【MongoDB】Shard key
1. 使用Shell命令分区
MongoDB提供的分区功能,本节简单介绍在mongo shell的分区命令。
- sh.enableSharding(database) 指定database
- sh.shardCollection(namespace, key, unique, options) 指定Collection
【注意】如果库中还没有指定的database则需要顺序执行上面两个命令,如果已经存在指定database,应该可以直接执行命令2。
还有一种命令格式是db.runCommand(),具体的参加官方文档:
https://docs.mongodb.com/manual/reference/command/enableSharding/#dbcmd.enableSharding
https://docs.mongodb.com/manual/reference/command/shardCollection/
2. Sharding Strategy
有两种常用的Sharding方式:hashed、ranged。
2.1 Hashed Sharding
Hashed Sharding方式使用在某一字段(Field)上指定哈希索引的方式指定其为shard key。
指定shard key例子:sh.shardCollection(“ccse.stu”, {“name”:”hashed”})
MongoDB自动计算哈希值,用户不需要对shard key进行哈希。
【注】不清楚MongoDB自带的哈希函数是什么。
哈希分片的好处是使得数据分区更加均匀,但是不支持范围查询,做范围查询就是在所有片上进行搜索。
2.2 Ranged Sharding
基于范围的分区的好处是能够支持范围查询,指定shard key:sh.shardCollection(“ccse.stu”, {“name” : 1, “height” : 1})。
范围分区可以指定多个字段,这和指定复合索引差不多。但是需要注意的是:
1. Hashed Sharding只能指定一个字段
2. Ranged Sharding不能同时指定hash字段,即像这样:sh.shardCollection("ccse.stu", {"name" : 1, "height" : "hashed"}),是不允许的。
下面Ranged Sharding下选取shard key的一些官方建议:
2.2.1 Shard Key的基数
Shard Key的基数决定了Chunk最多有多少。因为同一Shard Key的被存储在一个Chunk中,Chunk分裂不会将同一Shard Key的拆分。
假如有如下模型的Document:
{
price : 20
month : 1
}
如果指定month为shard key,那么最多只要12个chunk,如果数据一多,那么只能是chunk不断增长,就算增加分片也没有意义。
如何想要指定的shard key的基数不大,可以考虑复合索引,再加一个基数大的字段。
2.2.2 Shard Key的频率
再以上面那个例子说明,如果6月的数据特别多,而其他月份的数据很少,这样就是频率问题了,也是需要注意的。
2.2.3 Shard Key非单调变化
假如2.2.1节中的例子选择price为shard key,如果shard key单调递增,那么数据虽然会被分布到不同节点,但在插入时有可能只会往一个节点上插入。因为shard key相近的分布在同一节点,这应该很好理解。
2.2.4 Unique Shard Key
对于一个分区的Collection,只有可能存在以下两种unique key:
1. _id
2. 在shard key上的建立的索引,或复合索引里shard key包含在首位。
3. Shard Key 的限制
Shard Key size
一个 shard key 大小不能超过512个字节
Shard Key是不可变的
如果你想要换另一种shad key,官方建议以下步骤:
- Dump all data from MongoDB into an external format.
- Drop the original sharded collection.
- Configure sharding using the new shard key.
- Pre-split the shard key range to ensure initial even distribution.
- Restore the dumped data into MongoDB.
简言之,就是先备份数据,然后删除,重新选择shard key,再导入数据。
Shard Key在文档中的值是不变的
- 不能换Shard Key
- 不能更新Shard Key的值
4. 一些实际经验总结
- 插入时Shard Key不能重复,否则报错_dup_key
- 更新时update文档必须指定Shard Key,如下图测试
参考
https://docs.mongodb.com/manual/core/sharding-shard-key/#shard-key-indexes
https://docs.mongodb.com/manual/core/sharded-cluster-requirements/
https://docs.mongodb.com/manual/reference/limits/#limits-shard-keys