我有一个带有2个分片的mongodb分片(比如A& B),每个分区有17GB的可用空间。我将包含对象ID的_id设置为分片键。
以下是用于设置db和collection的命令。
sh.enableSharding("testShard");
sh.shardCollection("testShard.shardedCollection", {_id:1});
然后我尝试向mongos服务器发出4,000,000次插入查询。我执行脚本4次以上。
for(var i=0; i<1000000; i++){
db.shardedCollection.insert({x:i});
}
使用_id作为分片键,根据我的理解,上面提到的4000000文档将适合1个分片,所有插入仅在分片中发生。
然而,结果并不像我预期的那样,在一个碎片中插入了约1,300万个文件,另外在B碎片中插入了约2,700万个文件。
为什么会这样?是否在分片设置命令中缺少某些内容?或者我的理解是错误的,也许在mongodb中有类似默认范围分片键的东西?
如果有人可以共享默认范围分片键的行为(没有标记识别),那将非常有用。
下面是sh.status()结果
shard key: { "_id" : 1 }
chunks:
B 5
A 5
{ "_id" : { "$minKey" : 1 } } -->> { "_id" : ObjectId("540c703398c7efdea6037cbc") } on : B Timestamp(6, 0)
{ "_id" : ObjectId("540c703398c7efdea6037cbc") } -->> { "_id" : ObjectId("540c703498c7efdea603bfe3") } on : A Timestamp(6, 1)
{ "_id" : ObjectId("540c703498c7efdea603bfe3") } -->> { "_id" : ObjectId("540c704398c7efdea605d818") } on : A Timestamp(3, 0)
{ "_id" : ObjectId("540c704398c7efdea605d818") } -->> { "_id" : ObjectId("540c705298c7efdea607f04e") } on : A Timestamp(4, 0)
{ "_id" : ObjectId("540c705298c7efdea607f04e") } -->> { "_id" : ObjectId("540c707098c7efdea60c20ba") } on : B Timestamp(5, 1)
{ "_id" : ObjectId("540c707098c7efdea60c20ba") } -->> { "_id" : ObjectId("540c7144319c0dbee096f7d6") } on : B Timestamp(2, 4)
{ "_id" : ObjectId("540c7144319c0dbee096f7d6") } -->> { "_id" : ObjectId("540c7183319c0dbee09f58ad") } on : B Timestamp(2, 6)
{ "_id" : ObjectId("540c7183319c0dbee09f58ad") } -->> { "_id" : ObjectId("540eb15ddace5b39fbc32239") } on : B Timestamp(4, 2)
{ "_id" : ObjectId("540eb15ddace5b39fbc32239") } -->> { "_id" : ObjectId("540eb192dace5b39fbca8a84") } on : A Timestamp(5, 2)
{ "_id" : ObjectId("540eb192dace5b39fbca8a84") } -->> { "_id" : { "$maxKey" : 1 } } on : A Timestamp(5, 3)
答案 0 :(得分:4)
正如@LalitAgarwal已经指出的那样,ObjectIds默认会生成一个错误的分片键。但是,如果您并不真正关心数据存在于哪个分片中,并且只想让写入操作和块在您的分片中均匀分布,那么很容易获得:
db.shardedCollection.ensureIndex({_id:"hashed"});
sh.enableSharding("testShard");
sh.shardCollection("testShard.shardedCollection", {_id:"hashed"});
然而,这带来了一些(通常可以忽略不计)的缺点:
更好的方法是找到非人为的分片键。有关详细信息,请阅读Considerations for Selecting Shard Keys。简而言之:
答案 1 :(得分:2)
是的,你是对的,应该去一个单一的碎片。但是,虽然单个分片上有插入,但平衡器也会平衡分片并将块移动到其他分片。
话虽如此,你应该做的是通过从你的mongos调用以下命令来停止/禁用平衡器。
http://docs.mongodb.org/manual/reference/method/sh.disableBalancing/#sh.disableBalancing
sh.disableBalancing(namespace)
//namespace string The namespace of the collection.
完成后,启动插件并查看所有插件的前进位置。
对于_id字段分片,你也可以看一下:
http://docs.mongodb.org/manual/faq/sharding/#can-you-shard-on-the-id-field
Be aware that ObjectId() values, which are the default value of the _id field,
increment as a timestamp. As a result, when used as a shard key, all new documents
inserted into the collection will initially belong to the same chunk on a single
shard. Although the system will eventually divide this chunk and migrate its contents
to distribute data more evenly, at any moment the cluster can only direct insert
operations at a single shard. This can limit the throughput of inserts. If most of
your write operations are updates, this limitation should not impact your performance.
However, if you have a high insert volume, this may be a limitation.