CosmosDB: производительность Linq vs SqlQuerySpec при запросе CosmosDB - PullRequest
0 голосов
/ 29 августа 2018

Я регулярно выполнял предикаты LINQ при запросах конкретных документов CosmosDB. Однако сегодня я заполнил свой CosmosDB более чем 100 тысячами документов. Спектакль был очень медленным. Поскольку SQL-запрос на портале Azure был заметно быстрее, я попытался использовать SqlQuerySpec. Вуаля! Это работало намного быстрее.

Может кто-нибудь сказать мне, что происходит под капотом при использовании предикатов Linq с CosmosDB и почему это замедляет мои запросы?

Приведенный ниже код используется в моем методе для получения документа. NB. Идентификатор - это ключ раздела в этом случае.

        var collectionUri = UriFactory.CreateDocumentCollectionUri(CDBdatabase, CDBcollection);

        var sqlStatement = new SqlQuerySpec
        {
            QueryText = "SELECT * FROM c where c.id = @id",
            Parameters = new SqlParameterCollection()
                {
                          new SqlParameter("@id", consumerId),
                },
        };

        IDocumentQuery<T> query = documentClient.CreateDocumentQuery<T>(
            collectionUri,
            sqlStatement,
            .AsDocumentQuery();

        List<ConsumerDetails> results = new List<ConsumerDetails>();
        while (query.HasMoreResults)
        {
            results.AddRange(await query.ExecuteNextAsync<ConsumerDetails>());
        }

        return results.FirstOrDefault();

В сравнении с более медленным кодом:

        return documentClient.CreateDocumentQuery<ConsumerDetails>(
            collectionUri,
            .Where(f => f.Id == consumerId).AsEnumerable().FirstOrDefault();

1 Ответ

0 голосов
/ 29 августа 2018

Ответ зависит от вашего запроса.

Две части кода, которые вы разместили, не совпадают.

Чтобы они были одинаковыми, второй должен выглядеть так:

var collectionUri = UriFactory.CreateDocumentCollectionUri(CDBdatabase, CDBcollection);

var query = documentClient.CreateDocumentQuery<ConsumerDetails>(
    collectionUri)
    .Where(f => f.Id == consumerId)
    .AsDocumentQuery();

List<ConsumerDetails> results = new List<ConsumerDetails>();
while (query.HasMoreResults)
{
    results.AddRange(await query.ExecuteNextAsync<ConsumerDetails>());
}

return results.FirstOrDefault();

В обоих случаях это SQL, который вы будете выполнять против CosmosDB. Тем не менее, в случае LINQ, LINQ переводчик включится, чтобы преобразовать ваше выражение в запрос SQL.

Также в примере SQL, поскольку вы указываете прямо на строчную букву id (которая является CosmosDB id), которая также является ключом раздела, CosmosDB распознает это и ограничит запрос от перекрестного раздела до раздел конкретный, что делает его быстрее и дешевле. .Where(f => f.Id == consumerId) (с заглавными буквами Id) после прохождения через поставщика LINQ будет преобразовано в SELECT * FROM c where c.Id = consumerId, если только не существует JsonAttribute("id"), украшающего свойство Id. Это означает, что вам нужно предоставить значение PartitionKey в FeedOptions для запроса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...