MongoDB: merge all empty chunks

How to merge all empty chunks on a sharded cluster.

Maurizio Merli
2 min readJul 9, 2014

Here is how to merge all empty chunks on a MongoDB sharded cluster.

Access the cluster through `mongos`:

# mongos —port 61017

Now dump all chunks:

> sh.status(true)

Chunks are sorted by shard key and mongos splits the key domain in many parts on different nodes.

We can verify if there are empty chunks in this way:

db.getSiblingDB(“config”)
.chunks
.find({ns: “test.users”})
.sort({shard: 1})
.forEach(function(chunk) {
var ds = db.getSiblingDB(“test”).runCommand({
datasize: “test.users”,
keyPattern: { “_id”: 1 },
min: chunk.min,
max: chunk.max });
if (ds.size == 0) {
print(“empty chunk: “ + chunk._id + "/" + chunk.shard);
}
})

This command dump all empty chunks.

Now what we can do is to merge all empty chunks with their next one to collapse the key domain fragment, if they are on the same shard.

And we can do this creating this function:

function mergeEmptyChunks() {
var minchunk = null;
var count = 0;
print(“stop balancer”);
sh.stopBalancer();
try {
db.getSiblingDB(“config”).chunks
.find({ns : “test.users”})
.sort({min: 1})
.forEach(function(chunk) {
var ds = db
.getSiblingDB(“test”)
.runCommand({
datasize: “test.users”,
keyPattern: { “_id”: 1 },
min: chunk.min,
max: chunk.max });
if (minchunk != null
&& minchunk.shard == chunk.shard) {
db.getSiblingDB(“admin”)
.runCommand({
mergeChunks: “test.users”,
bounds: [ minchunk.min, chunk.max ] });
print(“merge chunk: “ + chunk._id
+ “ shard: “ + chunk.shard
+ “ size: “ + ds.size
+ “ #” + count);
}
if (ds.size == 0) {
if (minchunk == null
|| minchunk.shard != chunk.shard) {
ds.shard = chunk.shard;
ds.min = chunk.min;
ds.max = chunk.max;
minchunk = ds;
count = 1;
print(“min chunk: “ + tojsononeline(ds));
} else {
count++;
}
} else {
minchunk = null;
}
});
} finally {
print(“start balancer”);
sh.startBalancer();
}
}

And using it:

> mergeEmptyChunks()

--

--