基本命令¶
查看集合是否分片 [1]¶
去config库中查询:
db.collections.find({$and: [ {'dropped':{$ne:true}}, // 没有被删除的 {'name':'/dbname/'}] // 根据数据库名进行模糊查询 })
查看数据分布:
use dbname db.colname.getShardDistribution() #可以查看数据分布
最简单的方法:
use databaseName; db.collectionName.stats().sharded #简单的返回true或者false
修改指定表为分片表¶
实例:
use <db>;
db.wei64_scale_data_info.createIndex({"_id":"hashed"});
use admin;
db.runCommand({"shardcollection":"<db>.wei64_scale_data_info","key":{"_id" : "hashed"}});
// 查看
use <db>;
db.wei64_scale_data_info.getShardDistribution();
基本¶
配置分片集群:
sh.addShard("rep_shard1/10.0.4.6:27018,10.0.4.7:27018,10.0.4.8:27018")
sh.addShard("rep_shard2/10.0.4.6:27019,10.0.4.7:27019,10.0.4.8:27019")
验证分片集群是否搭建成功:
> sh.status()
shards:
{ "_id" : "rep_shard1", "host" : "rep_shard1/10.0.4.6:27018,10.0.4.7:27018,10.0.4.8:27018", "state" : 1 }
{ "_id" : "rep_shard2", "host" : "rep_shard2/10.0.4.6:27019,10.0.4.7:27019,10.0.4.8:27019", "state" : 1 }
将均衡器的迁移 chunk 时间控制在凌晨 02 点至凌晨 06 点:
use config
db.settings.update(
{ _id: "balancer" },
{ $set: { activeWindow : { start : "02:00", stop : "06:00" } } },
{ upsert: true }
)
将 chunk 的大小调整为 1MB:
> use config
> db.settings.save({_id:"chunksize",value:1})
> db.serverStatus().sharding
{
"configsvrConnectionString" : "confsvr/10.0.4.6:20000,10.0.4.7:20000,10.0.4.8:20000",
"lastSeenConfigServerOpTime" : {
"ts" : Timestamp(1566895485, 2),
"t" : NumberLong(16)
},
"maxChunkSizeInBytes" : NumberLong(1048576)
}
基于 Ranged 分片¶
开启 test 库的分片功能:
> sh.enableSharding("test")
对指定集合分片:
// MongoDB 会自动为 age 字段创建索引
> sh.shardCollection("test.test_shard",{"age": 1})
观察分片效果:
> sh.status()
test.test_shard
shard key: { "age" : 1 }
unique: false
balancing: true
chunks:
rep_shard1 2
rep_shard2 3
{ "age" : { "$minKey" : 1 } } --<< { "age" : 0 } on : rep_shard1 Timestamp(2, 0)
{ "age" : 0 } --<< { "age" : 36 } on : rep_shard1 Timestamp(3, 0)
{ "age" : 36 } --<< { "age" : 73 } on : rep_shard2 Timestamp(2, 3)
{ "age" : 73 } --<< { "age" : 92 } on : rep_shard2 Timestamp(2, 4)
{ "age" : 92 } --<< { "age" : { "$maxKey" : 1 } } on : rep_shard2 Timestamp(3, 1)
说明:
test.test_shard 集合总共有 2 个分片
分片 rep_shard1 上有 2 个 chunk,分片 rep_shard2 上有 3 个 chunk
年龄大于或等于 0 并且小于 36 的文档数据放到了第一个分片 rep_shard1
年龄大于或等于 36 并且小于 73 的文档数据放到了第二个分片 rep_shard2
此时已经达到了分片的效果
使用 find 命令来确认是否对应的数据存在相应的分片:
> db.test_shard.find({ age: { $gte : 36 ,$lt : 73 } }).explain()
{
"queryPlanner" : {
"winningPlan" : {
"stage" : "SINGLE_SHARD",
"shards" : [
{
"shardName" : "rep_shard2",
"connectionString" : "rep_shard2/10.0.4.6:27019,10.0.4.7:27019,10.0.4.8:27019",
"namespace" : "test.test_shard",
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "SHARDING_FILTER",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"age" : 1
},
"indexName" : "age_1",
"direction" : "forward",
"indexBounds" : {
"age" : [
"[36.0, 73.0)"
]
}
}
}
},
}
]
}
}
}
说明:
当查找年龄范围为大于等于 36 并且小于 73 的文档数据
MongoDB 会直接定位到分片 rep_shard2,从而避免全分片扫描以提高查找效率
扩展:
如果将 $gte : 36 改为 $gte : 35
MongoDB 会扫描全部分片
执行计划的结果将由 SINGLE_SHARD 变为 SHARD_MERGE
基于 Hashed 分片¶
创建的是 hash 索引分片:
sh.shardCollection("test.test_shard",{"age": "hashed"})
观察分片效果:
> sh.status()
chunks:
rep_shard1 2
rep_shard2 2
{ "age" : { "$minKey" : 1 } } --<< { "age" : NumberLong("-4611686018427387902") } on : rep_shard1 Timestamp(1, 0)
{ "age" : NumberLong("-4611686018427387902") } --<< { "age" : NumberLong(0) } on : rep_shard1 Timestamp(1, 1)
{ "age" : NumberLong(0) } --<< { "age" : NumberLong("4611686018427387902") } on : rep_shard2 Timestamp(1, 2)
{ "age" : NumberLong("4611686018427387902") } --<< { "age" : { "$maxKey" : 1 } } on : rep_shard2 Timestamp(1, 3)
说明:
总共有 4 个 chunk,分片 rep_shard1 有 2 个 chunk,分片 rep_shard2 有 2 个 chunk
分片后按照分片值 hash 后,存放到对应不同的分片
explain分析:
> db.test_shard.find({ age: { $gte : 36 ,$lt : 73 } }).explain()
{
"queryPlanner" : {
"winningPlan" : {
"stage" : "SHARD_MERGE",
"shards" : [
{
"shardName" : "rep_shard1",
"connectionString" : "rep_shard1/10.0.4.6:27018,10.0.4.7:27018,10.0.4.8:27018",
"winningPlan" : {
"stage" : "SHARDING_FILTER",
"inputStage" : {
"stage" : "COLLSCAN",
}
}
},
{
"shardName" : "rep_shard2",
"connectionString" : "rep_shard2/10.0.4.6:27019,10.0.4.7:27019,10.0.4.8:27019",
"winningPlan" : {
"stage" : "SHARDING_FILTER",
"inputStage" : {
"stage" : "COLLSCAN",
}
}
}
]
}
}
}
结论:
对于范围查找,基于 Hashed 的分片很可能需要全部分片都扫描一遍才能找到对应的数据,效率比较低下
如果等值查找,基于 Hashed 分片查找效率很高,直接定位到一个分片就可以返回满足条件的数据,无需进行全部分片的查找
查看主从关系:
> rs.isMaster()