2013-03-15 49 views
5

我已經做了很多的研究使用這些源表的存儲和它的大小限制,開銷等:的Windows Azure表存儲行大小限制爲小於規定1MB

使用這些信息我寫了一些代碼來有效地存儲跨多個屬性的二進制數據,計算任何行和屬性開銷並保持在64KB屬性限制和1MB行限制內。

不幸的是,它只是不起作用。作爲存儲大約0.5MB的示例,將返回一個400錯誤的請求,說明該實體太大 - 我不明白爲什麼會給出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> 

我一直在使用的代碼是相當簡單的,但我可能在估計開銷所犯的錯誤 - 但我懷疑它會在數據大小的100%離開..

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

馬蒂亞斯,你指的是實際的存儲服務,但你的目標在本地存儲模擬器的限制。模擬器使用本地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. 
+0

謝謝,我很懷疑,但MSDN主題有助於確認它。 – 2013-03-18 08:35:02

+1

'小於1MB'聽起來含糊,只是好奇,模擬器上的實際限制是什麼...... – JustAMartin 2016-03-30 14:55:46