我已经使用这些来源对表存储及其大小限制,开销等进行了大量研究:
使用这些信息,我编写了一些代码来有效地存储多个属性中的二进制数据,计算任何行和属性开销,并保持在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>
我一直在使用的代码非常直接,但我可能在估算开销方面犯了错误 - 但是我怀疑它会因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;
}
}
任何帮助解释我缺少的东西都表示赞赏!
谢谢,
的Mattias
答案 0 :(得分:4)
Mattias,您所引用的限制是针对实际的存储服务,但您的目标是本地存储模拟器。模拟器使用本地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.
答案 1 :(得分:0)
我认为 kwill 的回答是正确的。然而,它回避了实际限制是什么的问题。在我自己的代码中,我想在单个实体中打包尽可能多的字节,因此我同时遇到了实体限制和请求正文限制。
在编写了一些繁琐的代码后,这就是我发现的。
在存储模拟器上,最大实体大小似乎基于分区键和/或行键(也可能是表名)。使用实体大小计算 provided in the Azure docs,最大实体大小大约为 393,250 字节。
这是我摆弄的代码: https://gist.github.com/joelverhagen/bca6e0f9ed8fa779fcabc5c2904505ae
我最好的猜测是模拟器的实体大小计算是错误的,这导致了这种差异。
我只是让我的代码通过检查存储 URI 的主机来检测模拟器是否正在运行(127.0.0.1 表示模拟器)。