How to use integer RowKeys in Azure table storage?

I have sequentially numbered objects that I want to keep using the Azure Table Service, however the RowKey column type is problematic. The object number must be stored in the RowKey column, so I can quickly query for objects ( PK = '..' && RowKey = 5), get the latest entities ( RowKey > 10) and request a specific set of objects ( RowKey > 5 && RowKey < 10).

Since RowKey should be a string, lower than comparisons are problematic ( "100" < "11"). I was thinking about adding zeros to numbers (so that "100" > "011"), but I cannot predict the number of entities (and therefore the number of zeros).

I know that I can just create an integer column, but I would lose the performance advantage of the indexed RowKey column (plus I have no other information suitable for RowKey). Has anyone had this problem before?

+3
source share
5 answers

I solved this problem by creating my own RowKeyclass that wraps around String and provides a method Increment.

Now I can determine the range of valid characters (for example, 0-9 + a-z + A-Z) and "count" in this range (for example az9 + 1 = aza, azZ + 1 = aA0). The advantage of this compared to using only numbers is that I have a much larger range of possible keys ( 62^ninstead 10^n).

, , . , 10 ~8*10^17 20 ~7*10^35.

, , , , - .

, , .

EDIT: , - - : 0 , (, /, \) (0-9) .

+1

, , , RowKey . , PartitionKey, , RowKey (, "scope-id" → "12-8374" ).

, enzi. Base64, , 16 . , , / .

/// <summary>
/// Gets the four character string representation of the specified integer id.
/// </summary>
/// <param name="number">The number to convert</param>
/// <param name="ascending">Indicates whether the encoded number will be sorted ascending or descending</param>
/// <returns>The encoded string representation of the number</returns>
public static string NumberToId(int number, bool ascending = true)
{
    if (!ascending)
        number = 16777215 - number;

    return new string(new[] { 
        SixBitToChar((byte)((number & 16515072) >> 18)), 
        SixBitToChar((byte)((number & 258048) >> 12)), 
        SixBitToChar((byte)((number & 4032) >> 6)), 
        SixBitToChar((byte)(number & 63)) });
}

/// <summary>
/// Gets the numeric identifier represented by the encoded string.
/// </summary>
/// <param name="id">The encoded string to convert</param>
/// <param name="ascending">Indicates whether the encoded number is sorted ascending or descending</param>
/// <returns>The decoded integer id</returns>
public static int IdToNumber(string id, bool ascending = true)
{
    var number = ((int)CharToSixBit(id[0]) << 18) | ((int)CharToSixBit(id[1]) << 12) | ((int)CharToSixBit(id[2]) << 6) | (int)CharToSixBit(id[3]);

    return ascending ? number : -1 * (number - 16777215);
}

/// <summary>
/// Converts the specified byte (representing 6 bits) to the correct character representation.
/// </summary>
/// <param name="b">The bits to convert</param>
/// <returns>The encoded character value</returns>
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)] 
static char SixBitToChar(byte b)
{
    if (b == 0)
        return '!';
    if (b == 1)
        return '$';
    if (b < 12)
        return (char)((int)b - 2 + (int)'0');
    if (b < 38)
        return (char)((int)b - 12 + (int)'A');
    return (char)((int)b - 38 + (int)'a');
}

/// <summary>
/// Coverts the specified encoded character into the corresponding bit representation.
/// </summary>
/// <param name="c">The encoded character to convert</param>
/// <returns>The bit representation of the character</returns>
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)] 
static byte CharToSixBit(char c)
{
    if (c == '!')
        return 0;
    if (c == '$')
        return 1;
    if (c <= '9')
        return (byte)((int)c - (int)'0' + 2);
    if (c <= 'Z')
        return (byte)((int)c - (int)'A' + 12);
    return (byte)((int)c - (int)'a' + 38);
}

false , , . ! $ Base64, RowKey. , , RowKey, . :

0 → !!!! asc zzzz desc

1000 → !! Dc asc zzkL desc

2000 → !! TE asc zzUj desc

3000 → !! - asc zzF5 desc

4000 → !! yU asc zz $T desc

5000 → ! $C6 asc zylr desc

6000 → ! $Rk asc zyWD desc

7000 → ! $hM asc zyGb desc

8000 → ! $x! asc zy0z desc

9000 → ! 0Ac asc zxnL desc

+5

, ( ). , - (0000,0001,0002,.....):

public class ReadingEntity : TableEntity
{
    public static string KeyLength = "000000000000000000000";
    public ReadingEntity(string partitionId, int keyId)
    {
        this.PartitionKey = partitionId;
        this.RowKey = keyId.ToString(KeyLength); ;


    }
    public ReadingEntity()
    {
    }
}


public IList<ReadingEntity> Get(string partitionName,int date,int enddate)
{
        CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

        // Create the CloudTable object that represents the "people" table.
        CloudTable table = tableClient.GetTableReference("Record");

        // Construct the query operation for all customer entities where PartitionKey="Smith".
        TableQuery<ReadingEntity> query = new TableQuery<ReadingEntity>().Where(TableQuery.CombineFilters(
    TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, partitionName),
    TableOperators.And,TableQuery.CombineFilters(
    TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.LessThan, enddate.ToString(ReadingEntity.KeyLength)), TableOperators.And,
    TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.GreaterThanOrEqual, date.ToString(ReadingEntity.KeyLength)))));
        return table.ExecuteQuery(query).ToList();
}

, .

+3

, Linq Azure.

- ...

public int ID 
{
    get
    {
        return int.Parse(RowKey);
    }
}

Linq...

.Where(e => e.ID > 1 && e.ID < 10);

"ID" , "" .

, , - , . , Azure Table Storage , , . quickwatch.

, , , . , - , OP. RowKey.CompareTo() Linq where .

0

All Articles