Azure cosmosdb Cosmos分区键上的STARTSWITH是否优化了跨分区查询的“扇出”?

Azure cosmosdb Cosmos分区键上的STARTSWITH是否优化了跨分区查询的“扇出”?,azure-cosmosdb,azure-cosmosdb-sqlapi,Azure Cosmosdb,Azure Cosmosdb Sqlapi,Microsoft明确指出,跨分区查询将查询分散到每个分区: 以下查询在分区键DeviceId上没有筛选器。因此,它必须扇出到针对每个分区的索引运行的所有物理分区: 所以我很好奇,是否可以通过对分区键(比如STARTSWITH)进行范围查询来优化扇出 为了测试它,我创建了一个包含七个文档的小型Cosmos DB: { 分区键:前缀1:, 编号:项目1A }, { 分区键:前缀1:, id:项目1B }, { 分区键:前缀1:, id:item1c }, { partitionKey:前缀x1x:

Microsoft明确指出,跨分区查询将查询分散到每个分区:

以下查询在分区键DeviceId上没有筛选器。因此,它必须扇出到针对每个分区的索引运行的所有物理分区:

所以我很好奇,是否可以通过对分区键(比如STARTSWITH)进行范围查询来优化扇出

为了测试它,我创建了一个包含七个文档的小型Cosmos DB:

{ 分区键:前缀1:, 编号:项目1A }, { 分区键:前缀1:, id:项目1B }, { 分区键:前缀1:, id:item1c }, { partitionKey:前缀x1x:, id:item1d }, { 分区键:prefix2:, 编号:项目2a }, { 分区键:prefix2:, 编号:2b }, { partitionKey:prefix3:, 编号:项目3A } 它具有带有分区键/partitionKey的默认索引策略。然后我运行了一系列查询:

选择*FROM c WHERE STARTSWITHc.partitionKey“prefix1” -实际申请费用:2.92卢比 从c中选择*,其中c.partitionKey='prefix1:'或c.partitionKey='prefix1X:' -实际申请费用:3.02卢比 选择*FROM c,其中STARTSWITHc.partitionKey'prefix1:' 从c中选择*其中c.partitionKey='prefix1:' -每个查询的实际请求费用为:2.89卢比 选择*FROM c WHERE STARTSWITHc.partitionKey“prefix2” 从c中选择*其中c.partitionKey='prefix2:' -每个查询的实际请求费用为:2.86卢比 选择*FROM c WHERE STARTSWITHc.partitionKey“prefix3” 从c中选择*其中c.partitionKey='prefix3:' -每个查询的实际请求费用为:2.83卢比 从c中选择*,其中c.partitionKey='prefix2:'或c.partitionKey='prefix3:' -实际申请费用:2.99卢比 重新运行查询时,请求费用是一致的。费用增长模式似乎与结果集和查询复杂性一致,但“或”查询除外。然而,我尝试了以下方法:

从c中选择* -实际申请费用:2.35卢比 而且,即使使用相等运算符,对所有分区的基本扇出也比针对特定分区更快。我不明白这是怎么回事

尽管如此,我的示例数据库非常小,只有七个文档。查询集可能不够大,无法信任结果

因此,如果我有数百万个文档,那么从c.partitionKey开始,“prefix”会比分散到所有分区更优化吗?

这表明有一些效率

对于Azure Cosmos DB,查询通常按照以下顺序执行,从最快/最高效到较慢/较低效率

使用单个分区键和项键 在单个分区键上使用筛选子句进行查询 在任何属性上没有相等或范围筛选器子句的查询 不带过滤器的查询
随着您的扩展,每个分区的数量会减少,直到最终每个分区键值都有自己的物理分区

因此:

如果我有数以百万计的文档,那么使用c.partitionKey启动“prefix”会比分散到所有分区更优化吗

这两个查询将在多个分区中展开


而且我非常确定,由于Azure Cosmos DB使用基于哈希的分区在物理分区之间分布逻辑分区,所以在具有公共前缀的分区键之间没有局部性,每个STARTSWITH查询都必须分散到所有物理分区。

我知道STARTSWITH可能会扫描“多个”分区。因此,重新表述我的问题-使用STARTSWITH是否会阻止扫描与STARTSWITH筛选器不匹配的分区?我希望扫描只发生在与筛选器匹配的分区上,而不是扫描与筛选器不匹配的分区。不,为什么?它怎么会知道呢?@4c74356b41我不确定我是否理解这个问题。基本上,Cosmos服务必须看到分区键上有一个条件的查询,就像使用相等运算符一样,并对其进行解析,以得出查询其余部分适用的分区集。或者,对于宇宙来说,任何比等式更复杂的东西都太复杂了,反而会散开,每个分区都会扫描所有文档,即使查询不适用于它。我认为您的答案是正确的,我最初的问题来自一个关于扇形的错误前提,因为我认为它扇形到逻辑分区,因为它们由分区键标识,但扇形是一个物理路由。一个完整的分区键(不是带有StartWith的分部键)将允许Cosmos以要运行查询的逻辑分区的物理集为目标,但由于我使用的是StartWith,它无法确定这一点,并且必须扇出到本地分区的所有物理集。我的问题的例子只有一个物理分区,所以这是一个糟糕的例子 单个物理分区使用相同的索引,因此物理路由非常重要。我问这个问题的原因是,我试图滥用分区键来为我提供多个数据命名空间,但为了提高性能,每个命名空间数据都分布在多个分区中。例如,100个逻辑分区用于doc-type-A,50个逻辑分区用于doc-type-B,然后在查询时,我只需要针对包含特定doc-type的分区。这些文档不需要位于同一逻辑分区中。