Запрос Azure DocumentDB становится медленным для более чем 1000 вызовов

Я пробую Azure DocumentDB, и все работает нормально, но когда я сравниваю его с хранилищем таблиц Azure, кажется, что чтение документов становится медленным, когда у меня более 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 раз?


person Somayeh Ghazvinian    schedule 29.09.2015    source источник


Ответы (2)


Если вы вызываете эту функцию (GetCandidateById) более 1000 раз в нагрузочном тесте или цикле, я предполагаю, что проблема производительности, с которой вы можете столкнуться, заключается в создании DocumentLink, а также DocumentCollection.

При запросе документов в DocumentDB вы должны кэшировать значение documentCollection.DocumentsLink, чтобы вам не приходилось запрашивать базу данных и коллекцию для каждого запроса.

Это уменьшит ваш запрос с 3 сетевых обращений туда и обратно до 1.

person Aram    schedule 29.09.2015

Как упомянул Арам, приведенный выше фрагмент кода не кэширует самоссылку на коллекцию.... поэтому метод делает 3 сетевых запроса (1 для извлечения базы данных, 1 для извлечения коллекции и 1 для извлечения документа).

Кэширование самоссылки для коллекции может сократить метод до одного сетевого запроса, что, в свою очередь, значительно повысит производительность метода.

Маршрутизация на основе идентификаторов

Поскольку приведенный выше фрагмент кода извлекает базу данных и коллекцию по идентификатору, я бы предложил еще одно улучшение — использовать маршрутизацию на основе идентификатора... это означает, что вы можете избежать необходимости запрашивать коллекцию для получения самоссылки.

Ниже приведен пример выполнения операции удаления документа с использованием самоссылки:

// 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);

Вот та же логика удаления документа с использованием маршрутизации на основе идентификатора (со строкой, созданной вручную):

// 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);

Дополнительные сведения см. в следующем сообщении блога: https://azure.microsoft.com/en-us/blog/azure-documentdb-bids-fond-farewell-to-self-links/

person Andrew Liu    schedule 06.10.2015