Windows Azure表存储行大小限制小于规定的1MB

Windows Azure表存储行大小限制小于规定的1MB,azure,azure-table-storage,Azure,Azure Table Storage,我使用以下来源对表存储及其大小限制、开销等进行了大量研究: 利用这些信息,我编写了一些代码来有效地跨多个属性存储二进制数据,计算任何行和属性开销,并保持在64KB属性限制和1MB行限制内 不幸的是,它就是不起作用。例如,存储大约0.5MB会返回一个400错误请求,说明实体太大——我不明白为什么会给出1MB行大小限制 <?xml version="1.0" encoding="utf-8" standalone="yes"?> <error xmlns="http://s

我使用以下来源对表存储及其大小限制、开销等进行了大量研究:

利用这些信息,我编写了一些代码来有效地跨多个属性存储二进制数据,计算任何行和属性开销,并保持在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;
    }
}
类程序
{
静态void Main(字符串[]参数)
{
var client=CloudStorageAccount.DevelopmentStorageAccount.CreateCloudTableClient();
var table=client.GetTableReference(“sometable”);
table.CreateIfNotExists();
const int row开销=4;
const int maxRowSize=1024*1024;//1MB行大小限制
const int maxProperties=252;//255减去3个系统属性
const int maxPropertySize=64*1024;//64KB属性大小限制
var stream=new MemoryStream(新字节[512*1024]);//0.5MB数据
var实体=新的DynamicTableEntity(“pk”、“rk”);
var buffer=新字节[maxPropertySize];
var keySize=(entity.PartitionKey.Length+entity.RowKey.Length)*2;
使用的变量=行开销+键大小;
对于(变量i=0;imaxProperties)
{
抛出新的ArgumentException(string.Format(“您已经超过了{0}.”,maxProperties的列限制));
}
var name=string.Concat(“d”,i);
var开销=CalculateProperty开销(名称,EdmType.Binary);
var read=stream.read(缓冲区,0,maxPropertySize-开销);
使用+=读取+开销;
如果(已使用>最大行大小)
{
抛出新ArgumentException(string.Format(“您已经超过了{0}字节的最大行大小。”,maxRowSize));
}
如果(读取>0)
{
变量数据=新字节[读取];
复制(缓冲区,0,数据,0,读取);
添加(名称,新的EntityProperty(数据));
}
其他的
{
打破
}
}
WriteLine(“总实体大小:{0}”,已使用);
table.Execute(TableOperation.InsertOrReplace(entity));
}
静态int CalculateProperty开销(字符串名称,EdmType类型)
{
const int propertyOverhead=8;
int-propertyNameSize=name.Length*2;
int-propertyTypeSize;
开关(类型)
{
大小写类型。二进制:
案例EdmType.Int32:
大小写类型。字符串:
propertyTypeSize=4;
打破
大小写类型。布尔值:
propertyTypeSize=1;
打破
案例EdmType.DateTime:
案例类型。双:
案例EdmType.Int64:
propertyTypeSize=8;
打破
案例类型。Guid:
propertyTypeSize=16;
打破
违约:
抛出新的NotSupportedException();
}
返回propertyOverhead+propertyNameSize+propertyTypeSize;
}
}
任何帮助我解释我所缺少的东西都是非常感谢的

谢谢


Mattias

Mattias,您提到的限制是针对实际的存储服务,但您的目标是本地存储模拟器。emulator使用您的本地SQL Server作为其备份存储,并且具有与实际存储服务不同的限制。有关更多信息,请参见,特别是这一行:

* The total size of a row in a table in the storage emulator is limited to less than 1 MB.

我认为奎尔的回答是正确的。然而,它回避了实际限制是什么的问题。在我自己的代码中,我希望在一个实体中打包尽可能多的字节,因此我同时遇到实体限制和请求体限制

在编写了一段精细的代码后,我发现了这一点

在storage emulator上,最大实体大小似乎基于分区键和/或行键(可能还有表名)。使用实体大小计算,最大实体大小约为393250字节。

以下是我处理过的代码:

我最好的猜测是emulator的实体大小计算是错误的,这导致了这种差异


我将通过检查存储URI的主机(127.0.0.1表示emulator),让我的代码检测emulator是否正在运行。

谢谢,我也这么怀疑,但MSDN主题有助于确认这一点。
小于1MB
听起来很模糊,只是好奇,emulator上的实际限制是什么。。。