Azure DocumentDB 查询超过 1000 次调用变慢

Azure DocumentDB query gets slow for more than 1000 calls

我正在试用 Azure DocumentDB,它一切正常,但是当我将它与 Azure table 存储进行比较时,当我有超过 1000 个文档时,读取文档似乎有点慢。

这是我的片段:

public class DocumentDBProvider
{
    private static string EndpointUrl = "https://YourDocumentDbName.documents.azure.com:443/";
    private static string AuthorizationKey = "Take this code from your Azure Management Portal";
    private static string DatabaseName = "InterviewDB";
    private static string DocumentCollectionName = "InterviewCollection";

    public async Task<DocumentCollection> CreateDatabaseAndDocumentCollection()
    {
        var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey);

        Database database = await client.CreateDatabaseAsync(new Database { Id = DatabaseName });

        DocumentCollection documentCollection = await client.CreateDocumentCollectionAsync(database.CollectionsLink,
                                                                                         new DocumentCollection { Id = DocumentCollectionName }
                                                                                           );
        return documentCollection;
    }

    public string GetDocumentLink()
    {
        var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey);
        Database database = client.CreateDatabaseQuery().Where(db => db.Id == DatabaseName).AsEnumerable().FirstOrDefault();
        DocumentCollection documentCollection = client.CreateDocumentCollectionQuery(database.CollectionsLink).Where(db => db.Id == DocumentCollectionName).AsEnumerable().FirstOrDefault();
        return documentCollection.DocumentsLink;
    }
    public DocumentClient GetClient()
    {
        return new DocumentClient(new Uri(EndpointUrl), AuthorizationKey);
    }

    public List<Candidate> GetCandidateById(int candidateId)
    {
        var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey);
        Database database = client.CreateDatabaseQuery().Where(db => db.Id == DatabaseName).AsEnumerable().FirstOrDefault();
        DocumentCollection documentCollection = client.CreateDocumentCollectionQuery(database.CollectionsLink).Where(db => db.Id == DocumentCollectionName).AsEnumerable().FirstOrDefault();

        return client.CreateDocumentQuery<Candidate>(documentCollection.DocumentsLink).Where(m => m.CandidateId == candidateId).Select(m => m).ToList();
    }

}

当我调用 GetCandidateById 函数 1000 次时,有什么想法会导致它加载缓慢吗?

如果您在负载测试或循环中调用此函数 (GetCandidateById) 超过 1000 次,我猜您可能面临的性能问题是创建 DocumentLink 作为以及 DocumentCollection.

在 DocumentDB 中查询文档时 - 您应该缓存 documentCollection.DocumentsLink 值,这样您就不必为每个查询查询数据库和集合。

这会将您的查询从 3 次网络往返减少到 1 次。

正如 Aram 所提到的,上面包含的代码片段不会缓存 Collection self-link...因此该方法发出 3 个网络请求(1 个用于检索数据库,1 个用于检索集合, 和 1 检索文档)。

为集合缓存self-link可以将方法减少为单个网络请求,进而大大提高方法的性能。

基于 Id 的路由

由于上面的代码片段通过 id 检索数据库和集合,我建议的另一项改进是使用基于 id 的路由...这意味着您可以避免查询集合来检索 self- link.

下面是使用self-links执行文档删除操作的例子:

// Get a Database by querying for it by id
Database db = client.CreateDatabaseQuery()
                    .Where(d => d.Id == "SalesDb")
                    .AsEnumerable()
                    .Single();

// Use that Database's SelfLink to query for a DocumentCollection by id
DocumentCollection coll = client.CreateDocumentCollectionQuery(db.SelfLink)
                                .Where(c => c.Id == "Catalog")
                                .AsEnumerable()
                                .Single();

// Use that Collection's SelfLink to query for a DocumentCollection by id
Document doc = client.CreateDocumentQuery(coll.SelfLink)
                     .Where(d => d.Id == "prd123")
                     .AsEnumerable()
                     .Single();

// Now that we have a doc, use it's SelfLink property to delete it
await client.DeleteDocumentAsync(doc.SelfLink);

这是使用基于 id 的路由(带有手动构建的字符串)的相同文档删除逻辑:

// Build up a link manually using ids
// If you are building up links manually, ensure that 
// the link does not end with a trailing '/' character
var docLink = string.Format("dbs/{0}/colls/{1}/docs/{2}", 
     "SalesDb", "Catalog", "prd123");

// Use this constructed link to delete the document
await client.DeleteDocumentAsync(docLink);

SDK 还包括一个 URI 工厂,可以用来代替手动构建字符串:

// Use UriFactory to build the DocumentLink
Uri docUri = UriFactory.CreateDocumentUri("SalesDb", "Catalog", "prd123");

// Use this constructed Uri to delete the document
await client.DeleteDocumentAsync(docUri);

查看以下博客post了解更多详情:https://azure.microsoft.com/en-us/blog/azure-documentdb-bids-fond-farewell-to-self-links/