Overview: I will go over sharding basics and how to overcome problems like calculating ranks and inbox.
Sharding is splitting your database into partitions and keeping each of the partitions on different servers.
The following figure will make it more clear.

Database Sharding Basic Overview
What we did is, instead of keeping details of all user on one database server, we kept the users with odd userid on one server and others on second server. Lets say, if our system allowed us to make only 1000 queries on user, we can now make 2000 (1000 on each server more or less). You can split your data into any number of shards and it scales horizontally.
Q1: How many shards (partitions)?
The main effort in sharding is upfront while doing the partiions. So its better to plan for next 6 months or so. Lets say have only 2 servers, you can partition into 10 shards and place 5 of them on one server and other 5 on second. Later on, if add one more server, you can move 2 shards each from first and second server onto the third one. You might ask why 10, let like many other decisions in startup, this is more about gut feel then anything else.
Now, how to implement sharding in your code. There are a number of options like mysql proxy but the easiest method (both in effort and maintenance) change your database api layer(the class in your codebase which handles the actual query execution, maintaining connections etc) and pass an extra parameter the userid. The database layer can determine the server and database name to use based on the userid. So:
apps_mysql_query(query) => apps_mysql_query(userid, query)
The biggest issue with sharding is how to compute something at a global level. Lets say in above example, each user had a score. You want to know the top 25 leaders. Earlier it was one simple query:
“SELECT userid, name, photo FROM user WHERE user = ‘active’ ORDER BY totalscore DESC LIMIT 10″
Since now you have 10 different shards, you need to execute the same query on 10 different shards, merge the results and select top 25 from this combined list. Downright Ugly!
To get around this problem, what needs to be done is maintain two snapshots of database, one sharded version and one complete version (called central repository). So what we now have is:

Sharding - Central Repository Model
Q2: Doesn’t this take away all advantage we had with sharding?
Not really. Actually far from it. You need to keep make a central repository of those tables on which you need to perform global queries. So User table is one. Tables like “User Permissions” or “User Actions Done” don’t need to be kept on central repository. Now why have a central repository for user table at all? Things like user complete details for user profile, user name and picture etc to show, all these will go to the corresponding user shard. But when you want to show things like leaderboard, only then you will query the central repository.
We need to change our database api so that if userid sent is null, it should query the central repository
Now, we come to the second problem. Let say, user 1 had sent a message to user 2, do we keep it on user1 shard or user2 shard. If we keep it on any one of them, to show messages recieved by user2 do we query all shards? The answer is, keep it on both shards. The one extra insert is much more efficient than 10 selects you will have to do each time user wants to see messages he has recieved. But doesn’t that increase data size? Isn’t disk space close to free
.
So how does our database api change to reflect the above:
apps_mysql_query(userid, query) => apps_mysql_query(userid1, userid2, query)
In case of write query, if userid2 is null, it will just write to shard 1, but in case userid2 is not null, it will write to both shards. In case of read, userid2 is ignored.
So thats it. Let me know in comments if you have used an alternative strategy or any feedback on current system.
March 21, 2009 at 7:34 am
Yo Frosty! I see you’ve put this on High Scalability as well … nice! However, since you tag this as intro to sharding, you might want to mention that this makes real sense for _huge_ datasets … for small volume apps the added complexity might impose a greater cost than benefit
March 21, 2009 at 7:49 am
I’m working on something similar to that.
I use a master lookup table to locate users, etc., to which shard they reside on. It turns out the data needed for leaderboard queries is very small: on the order of bytes. So I just keep that right in the main lookup table. I recalculate those values with a batch job at night.
If you keep a whole separate copy of certain tables, you may eventually run into a write bottleneck — which is usually the reason for moving to shards in the first place.
March 21, 2009 at 8:06 am
@amitava: nice suggestion. but not sure i should edit the post since its been approved for earlier content. Anywaz you already mentioned in comments
.
@mark: actually in our app, we had to show leaderboard data live(cache of few minutes only) so that user can compete with each other and try to overtake.
We had actually discussed the same thing while designing the system. The solution we came up was include a write cache in front of central repository when we run into the bottleneck but i guess we still have a lot of runway left before we will actually need to implement that.
Also in term of sizes, we had two tables (user and content submitted) which we kept on central repository both of which had millions, while other data like comments, votes, userfeed etc were running into billions and had to be sharded asap.
March 21, 2009 at 8:26 am
It sounds like you’re building a very similar application to me!
Come to think of it, I think I’ve just thought of an effective way to do live ranks, even with hundreds of thousands of active users. I’ll have to look more into it. Thanks for the inspiration that it’s indeed possible!
March 21, 2009 at 9:12 am
@forsty Nice post .. A great intro post. Infact Pravu da also wrote a post on sharding sometime back http://pravanjan.wordpress.com/2009/03/03/the-art-of-slicing-data/
KK left a great link from one of the developers of NetLog. I thought they are doing a very flexible directory based lookup for shards. Here is the blog post for your readers reference http://www.jurriaanpersyn.com/archives/2009/02/12/database-sharding-at-netlog-with-mysql-and-php/
March 22, 2009 at 8:36 am
[...] Database Sharding Basics and User Rank Calculation [...]
March 22, 2009 at 11:34 am
[...] Database Sharding Basics and User Rank Calculation ” “The Frozen World” [...]
March 23, 2009 at 6:46 pm
Hi,
Thanks for sharing your ideas.
I’d prefer to use some kind of memory based caching system (or MySQL cluster) for leaderboards and lookup tables and update the cache when needed. For example, when users’ ranks change then update the cache.
Querying disk data for leaderboard generation might not work with millions of users in an efficient way. Or at least use summary tables (possible in Memory using MySQL’s MEMORY storage engine).
In that case you’ll also need some type of startup DB scripts to provide the initial data in case of system restarts etc.
Thanks.
March 23, 2009 at 7:31 pm
[...] Database Sharding Basics and User Rank Calculation « "The Frozen World" – [...]
March 26, 2009 at 8:21 pm
This is a very good, simple explanation of DB sharding — thank you for writing the post.
I cringed when I read the line about splitting users from the same table into fractions of a table’s data set! It’s a good start, but I’m a proponent of organizing data in ways that leverage the nature of the data rather than splitting a data set arbitratily. Some data sets are heavier than others — this is a fact of life; embracing the differences in data sets shows that we understand our problem space and it can also provide organic constraints for our systems. This improves the scalability of a sharded DB. If we can find a natural line to split data on (like splitting namespaces into separate tables, which can each reside on any DB server shard you need them to) we’re also more likely to be able to fit an entire table in the DB server’s memory, which means faster query times. Depending on the architecture and the amount of data in its popular tables, we could then scale up any one (or more) of the DB servers in order to fit the frequently accessed tables in memory during peak hours.
There are also emergent properties that arise when we effectively leverage the nature of data. Some queries will inherently be faster; some data sets won’t require as much sorting; some data sets will be reduced in size (maybe even reduced to one result row); patterns in data requests can become more apparent; etc. And don’t forget that hashing functions can change the nature of data.
March 27, 2009 at 11:56 am
[...] Database sharding [...]
April 3, 2009 at 7:51 pm
The reason for sharding is because the write load is too high for one server. With this solution, the central store needs to be much faster (read: more expensive) because it needs to process the amount of write requests of all other nodes combined.
You should not be afraid of running the same (simple) query on many different machines. As long as your driver/programming language allows you to do asynchronous and parallel IO you can fire off 100 queries at the same time. Facebook fetches hundreds of memcached entries per pageview, Amazon invokes one hundred services for a pageview. It’s not a shame.
May 13, 2009 at 5:28 pm
Hi Frosty, Nice post. One observation though.. you mentioned that you’ll go over the user ranks problem.. and the idea you’ve given is fine for maintaining the leader-board but would it scale for fetching the rank of any user?
December 5, 2011 at 4:15 pm
Hi there,
Very interesting information. Gave me a head start on what i was looking for.
But the only thing i am worried is for eg. signing up and checking for email duplication! I liked the idea of checking the main table but then when it grows too big, wont it be a prob?
and wont it be too slow too if i need to chehck all users’ sharded table which can reside on a different server?
Does anybody have any idea?
Thanks a lot again for your input.
March 3, 2013 at 7:05 am
Write more, thats all I have to say. Literally, it seems as though you relied on the video to make your point.
You clearly know what youre talking about, why waste your intelligence on just
posting videos to your site when you could be giving us something informative to read?