Heya Kristinn --
If I understand correctly, when you say that you've changed the sharding key, you mean that you have changed the format of the string you're writing to the field which is used as the shard key. However, the chunks were split according to the old format, and the system has not, as yet, seen fit to come up with a new set of splits, and you are thus still experiencing hotspots.
To understand what is (or in this case is not) happening, you should familiarize yourself with how MongoDB handles automatic chunk splitting [1]. Namely, it is looking for chunks which are above a certain size, and the next time that chunk mutates (receives an insert or update), it will be divided in two. As a later step, the balancer will attempt to maintain a roughly equal number of chunks across all of it's shards. [4]
Thus, one possible course of action is to force MongoDB to split chunks more than it has. There's two options for doing this:
- Telling MongoDB to split at a smaller chunk size. [2]
- Forcing some manual splits. [3]
The first option is far safer. The second will likely take effect sooner.
If choosing a smaller chunk size, it should only temporarily be lowered, else risking the caveats of small chunk sizes mentioned in [1].
However, this general course of action has a hidden catch. Namely, you already have several chunks that have been created, and many of them will be empty, or effectively close enough to empty. A glance at how the balancer chooses migration [4], and you'll see it attempts to balance according to the number of chunks on each shard. Thus, you're at risk of having several of these empty chunks landing on the same shard, giving that shard a disproportionately low amount of the load, making all the other shards hotter. How bad this effect will be is a function of how many chunks already exist, how many will be later created, and how the semi-random nature of balancing decides to arrange chunks to shards.
You can use db.collection.getShardDistribution() from the mongo shell to get a better feel for how the balancer is functioning for you.
There is no easy remedy to this situation, as chunks, once split, last forever.
An alternative solution to your situation, which avoids this problem, is to create a new sharded collection, with a more suitable shard key. Then, set up a process which moves all your documents from the old collection to the new one. This solution works best if you can take some downtime, since you won't need your application to understand how to perform reads and writes across both collections at once. This solution is superior in it's end result, but likely requires much more effort to implement.
If you choose to go with the "new collection" method, there's a couple things to consider:
- Pre-splitting the chunks can allow for the initial loading to be faster. [5]
- You have a clean slate. If you supply me with a couple sample documents, as well as a description of how the documents get created, updated, and queried, I can assist you with choosing a more optimal key. There's more than just write hotspots to consider.
Hope this helps!
-- Rod
References: