在查询CosmosDB特定文档时,我经常执行LINQ谓词。但是,今天我用100 k +文件填满了我的CosmosDB。表现非常缓慢。由于Azure门户中的SQL查询明显更快,我尝试使用SqlQuerySpec。瞧!它工作得更快。
任何人都能告诉我幕后发生的事情,当使用Linq谓词与CosmosDB时,为什么它会减慢我的查询速度?
以下代码用于获取文档的方法中。注意:在这种情况下,id是分区键。
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();
答案取决于您查询的方式。
您发布的两个代码段不一样。
对于他们来说,第二个必须看起来像这样:
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();
在这两种情况下,您将针对CosmosDB执行SQL。但是在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
值。