5

これらのソースを使用して、テーブルストレージとそのサイズ制限、オーバーヘッドなどについて多くの調査を行いました。

この情報を使用して、複数のプロパティにまたがるバイナリ データを効果的に格納し、行とプロパティのオーバーヘッドを計算して、64KB のプロパティ制限と 1MB の行制限内に収まるようにコードを作成しました。

残念ながら、それは機能しません。例として、約 0.5MB を格納すると、エンティティが大きすぎることを示す 400 Bad Request が返されます。1MB の行サイズ制限が与えられる理由がわかりません。

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
  <code>EntityTooLarge</code>
  <message xml:lang="en-GB">The entity is larger than allowed by the Table Service.</message>
</error>

私が使用してきたコードはかなり単純ですが、オーバーヘッドの見積もりで間違いを犯した可能性があります.

class Program
{
    static void Main(string[] args)
    {
        var client = CloudStorageAccount.DevelopmentStorageAccount.CreateCloudTableClient();
        var table = client.GetTableReference("sometable");
        table.CreateIfNotExists();

        const int rowOverhead = 4;
        const int maxRowSize = 1024 * 1024; // 1MB row size limit
        const int maxProperties = 252; // 255 less 3 system properties
        const int maxPropertySize = 64 * 1024; // 64KB property size limit

        var stream = new MemoryStream(new byte[512 * 1024]); // 0.5MB of data
        var entity = new DynamicTableEntity("pk", "rk");
        var buffer = new byte[maxPropertySize];
        var keySize = (entity.PartitionKey.Length + entity.RowKey.Length) * 2;
        var used = rowOverhead + keySize;

        for (var i = 0; i < maxProperties + 1; i++)
        {
            if (i > maxProperties)
            {
                throw new ArgumentException(string.Format("You have exceeded the column limit of {0}.", maxProperties));
            }

            var name = string.Concat("d", i);
            var overhead = CalculatePropertyOverhead(name, EdmType.Binary);
            var read = stream.Read(buffer, 0, maxPropertySize - overhead);
            used += read + overhead;

            if (used > maxRowSize)
            {
                throw new ArgumentException(string.Format("You have exceeded the max row size of {0} bytes.", maxRowSize));
            }

            if (read > 0)
            {
                var data = new byte[read];
                Array.Copy(buffer, 0, data, 0, read);
                entity.Properties.Add(name, new EntityProperty(data));
            }
            else
            {
                break;
            }
        }

        Console.WriteLine("Total entity size: {0}", used);
        table.Execute(TableOperation.InsertOrReplace(entity));
    }

    static int CalculatePropertyOverhead(string name, EdmType type)
    {
        const int propertyOverhead = 8;
        int propertyNameSize = name.Length * 2;
        int propertyTypeSize;

        switch (type)
        {
            case EdmType.Binary:
            case EdmType.Int32:
            case EdmType.String:
                propertyTypeSize = 4;
                break;
            case EdmType.Boolean:
                propertyTypeSize = 1;
                break;
            case EdmType.DateTime:
            case EdmType.Double:
            case EdmType.Int64:
                propertyTypeSize = 8;
                break;
            case EdmType.Guid:
                propertyTypeSize = 16;
                break;
            default:
                throw new NotSupportedException();
        }

        return propertyOverhead + propertyNameSize + propertyTypeSize;
    }
}

私が欠けているものを説明するのに助けていただければ幸いです!

ありがとう、

マティアス

4

2 に答える 2

4

Mattias さん、あなたが言及している制限は実際の Storage Service に対するものですが、ローカルの Storage Emulator をターゲットにしています。エミュレーターはローカル SQL Server をバッキング ストアとして使用し、実際のストレージ サービスとは異なる制限があります。詳細については、 http://msdn.microsoft.com/en-us/library/windowsazure/gg433135.aspx (特に次の行) を参照してください。

* The total size of a row in a table in the storage emulator is limited to less than 1 MB.
于 2013-03-15T16:14:48.367 に答える