我有一个相当庞大的(30毫升行,每个最多5-100Kb)表在Azure上
每个RowKey
都是Guid,PartitionKey
是第一个Guid部分,例如:
PartitionKey = "1bbe3d4b"
RowKey = "1bbe3d4b-2230-4b4f-8f5f-fe5fe1d4d006"
表每秒有600次读取和600次写入(更新),平均延迟为60ms 。所有查询都使用PartitionKey
和RowKey
但是,有些读取需要高达3000ms (!)。平均而言,所有读取的> 1%需要超过500毫秒且与实体大小无关(在25毫秒内可返回100Kb行,在1500毫秒内可返回10Kb)。
我的应用程序是在4-5个大型实例上运行的ASP.Net MVC 4网站。
我已阅读有关Azure表存储性能目标的所有MSDN文章,并已完成以下操作:
UseNagle
已关闭Expect100Continue
也已停用MaxConnections
表客户端设置为250(设置1000-5000没有任何意义)我也检查过:
这种性能问题可能是什么原因以及如何改进?
答案 0 :(得分:1)
如果我不打算很快更新实体,我会使用MergeOption.NoTracking属性上的DataServiceContext.MergeOption设置来获得额外的性能。这是一个例子:
var account = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue("DataConnectionString"));
var tableStorageServiceContext = new AzureTableStorageServiceContext(account.TableEndpoint.ToString(), account.Credentials);
tableStorageServiceContext.RetryPolicy = RetryPolicies.Retry(3, TimeSpan.FromSeconds(1));
tableStorageServiceContext.MergeOption = MergeOption.NoTracking;
tableStorageServiceContext.AddObject(AzureTableStorageServiceContext.CloudLogEntityName, newItem);
tableStorageServiceContext.SaveChangesWithRetries();
另一个问题可能是你正在检索整个enity及其所有属性,即使你只打算使用一个或两个属性 - 这当然是浪费,但不容易避免。但是,如果您使用Slazure,那么您可以使用查询投影仅从表存储中检索您感兴趣的实体属性,而不会更多,这将为您提供更好的查询性能。这是一个例子:
using SysSurge.Slazure;
using SysSurge.Slazure.Linq;
using SysSurge.Slazure.Linq.QueryParser;
namespace TableOperations
{
public class MemberInfo
{
public string GetRichMembers()
{
// Get a reference to the table storage
dynamic storage = new QueryableStorage<DynEntity>("UseDevelopmentStorage=true");
// Build table query and make sure it only return members that earn more than $60k/yr
// by using a "Where" query filter, and make sure that only the "Name" and
// "Salary" entity properties are retrieved from the table storage to make the
// query quicker.
QueryableTable<DynEntity> membersTable = storage.WebsiteMembers;
var memberQuery = membersTable.Where("Salary > 60000").Select("new(Name, Salary)");
var result = "";
// Cast the query result to a dynamic so that we can get access its dynamic properties
foreach (dynamic member in memberQuery)
{
// Show some information about the member
result += "LINQ query result: Name=" + member.Name + ", Salary=" + member.Salary + "<br>";
}
return result;
}
}
}
完全披露:我编写了Slazure。
如果要检索大型数据集,也可以考虑分页,例如:
// Retrieve 50 members but also skip the first 50 members
var memberQuery = membersTable.Where("Salary > 60000").Take(50).Skip(50);
答案 1 :(得分:0)
通常,如果特定查询需要扫描大量行,则需要更长时间。您看到的行为是否特定于查询/数据?或者,您是否看到相同数据和查询的性能不同?