Reputation: 11247
I am building my own sharding solution with ASP.NET C# and MySQL. For the Id of each row I use the following:
So for example, an ID should be in the url like this:
http://mywebsite.com/folders/65535655354294967297
What I want to know is how to combine the numbers into a big number so I can extract the data later on. So for example, I won't use 1 as the shard ID, I would probably need to you 00001 because later it will be easier to extract that number by making a division on the whole number.
So how can I do that, what is the best way to build a long number with three seperate numerical values and then be able to extract them back in code?
I look for the most efficient way to do it in C#
Thanks.
Upvotes: 0
Views: 279
Reputation: 116138
You can use hex represantations of numbers
ushort ShardId=1;
ushort TableTypeId = 100;
uint IncrementalNumber = 1000;
string url = ShardId.ToString("X4") + TableTypeId.ToString("X4")
+ IncrementalNumber.ToString("X8");
var i1 = Convert.ToUInt16(url.Substring(0, 4), 16);
var i2 = Convert.ToUInt16(url.Substring(4, 4), 16);
var i3 = Convert.ToUInt32(url.Substring(8, 8), 16);
OR
string url = (((ulong)ShardId << 48) | ((ulong)TableTypeId << 32) | IncrementalNumber)
.ToString("X16");
var u = Convert.ToUInt64(url,16);
var i1 = (ushort)(u >> 48);
var i2 = (ushort)((u >> 32) & 0xffff);
var i3 = (uint)(u & 0xffffffff);
Upvotes: 1
Reputation: 4043
You pretty much described the answer in your problem. Define a fixed width for each number.
int iShardId = 12; // Fixed width of 5
int iTableTypeId = 840; // Fixed width of 5
long lIncremental = 967295; // Fixed width of 10
string sMyId = String.Concat(iShardId.ToString("00000"), iTableTypeId.ToString("00000"), lIncremental.ToString("0000000000"));
You can then parse the string later (through an iHttpModule or whatever) using RegEx:
RegEx rMyText = new RegEx(@"/(?<shard>[0-9]{5})(?<table>[0-9]{5})(?<inc>[0-9]{10})/?$");
Match mMyValues = rMyText.Match(Request.Url.AbsolutePath);
if (mMyValues.Success) {
int iShardId = Convert.ToInt32(mMyValues["shard"].Value);
int iTableTypeId = Convert.ToInt32(mMyValues["table"].Value);
long lIncremental = Convert.ToInt64(mMyValues["inc"].Value);
}
else {
//The input didn't match
}
The RegEx is intended as a sample to parse the numbers, but obviously depending on how you plan to implement, you should adjust it to make sure that the input is limited to the values you are expecting by using beginning/terminating slashes or end of string ($).
Upvotes: 2
Reputation: 578
A solution could be to use binary numbers and append them together to form a single number.
- Shard Id - Int (1-65535)
- Table Type Id - Small Int (1-65535)
- Incremental number (1 - 4294967295)
The Shard Id and the Table Id both requires 16 bit, and the Incremental number requires 16 bit. This means you can represent the data with 64 bits.
Example:
Shard Id
Dec: 7
Bin: 0000 0000 0000 0111
Table Type Id
Dec: 2435
Bin: 0000 1001 1000 0011
Incremental number
Dec: 23456457
Bin: 0001 0110 0101 1110 1010 1100 1001
Final number
Concat the binary values like
Shard id + table type id + incremental number
Bin: 0000 0000 0000 0111 0000 1001 1000 0011 0000 0001 0110 0101 1110 1010 1100 1001
Dec: 1980783105796809
Upvotes: 1
Reputation: 50114
Several options, roughly from longest (most readable?) to shortest (least readable)
00001000010000000001
)1-1-1
or 1/1/1
)ushort
s and uint
into a ulong
and put that in the URLI'd go with the second one - it's probably going to be shortest most of the time and is most human-readable.
Upvotes: 0