首页 > 解决方案 > 两个数据库中的镜像数据产生截然不同的 RU 消耗

问题描述

我正在使用 Azure Cosmos 将客户数据存储在我的多租户应用程序中。我的一位客户开始抱怨在查询他们的数据时等待时间过长。作为快速修复,我为他们创建了一个专用的 Cosmos 实例并将他们的数据复制到该专用实例。现在我有两个数据库,其中包含该客户数据的精确副本。我们将这些数据库称为 db1 和 db2。db1 包含所有客户的所有数据,包括该客户。db2 仅包含该客户的相关数据。此外,对于这两个数据库,分区键是租户 ID 和日期的聚合,称为ownerTime. 此外,每个数据库都包含一个名为“call”的容器。

然后我在两个数据库中运行这个查询:

select c.id,c.callTime,c.direction,c.action,c.result,c.duration,c.hasR,c.hasV,c.callersIndexed,c.callers,c.files,c.tags_s,c.ownerTime
from c
where
c.ownerTime = '352897067_202011'
and c.callTime>='2020-11-01T00:00:00'
and c.callTime<='2020-11-30T59:59:59'
and (CONTAINS(c.phoneNums_s, '7941521523'))

如您所见,我正在隔离一个分区(ownerTime: 352897067_202011)。在这个分区中,每个数据库大约有 50,000 条记录。

在 db1(包含所有客户数据的数据库)中,这使用了 5116.38 个 RU。在 db2(专用实例)中,此查询使用 65.8 个 RU。

为什么会出现这种差异?这两个分区中的数据在两个数据库中完全相同。索引策略也完全相同。我怀疑 db1 正在尝试进行扇出查询。但它为什么要这样做呢?我已经设置了查询,以便它只会在这个分区中查找。

以下是我在每个数据库上运行后为上述查询检索到的统计信息:

db1

Request Charge:                        5116.38 RUs
Retrieved document count:              8
Retrieved document size:               18168 bytes
Output document count:                 7
Output document size:                  11793 bytes
Index hit document count:              7
Index lookup time:                     5521.42 ms
Document load time:                    7.8100000000000005 ms
Query engine execution time:           0.23 ms
System function execution time:        0.01 ms
User defined function execution time:  0 ms
Document write time:                   0.07 ms
Round Trips:                           1

数据库2

Request Charge:                        65.8 RUs
Showing Results:                       1 - 7
Retrieved document count:              7
Retrieved document size:               16585 bytes
Output document count:                 7
Output document size:                  11744 bytes
Index hit document count:              7
Index lookup time:                     20.720000000000002 ms
Document load time:                    4.8099 ms
Query engine execution time:           0.2001 ms
System function execution time:        0.01 ms
User defined function execution time:  0 ms
Document write time:                   0.05 ms
Round Trips:                           1

两个数据库的索引策略是:

{
    "indexingMode": "consistent",
    "automatic": true,
    "includedPaths": [
        {
            "path": "/*"
        }
    ],
    "excludedPaths": [
        {
            "path": "/\"_etag\"/?"
        },
        {
            "path": "/callers/*"
        },
        {
            "path": "/files/*"
        }
    ]
}

*更新:我最近用更清晰的查询更新了这个问题,并返回了查询统计信息。

标签: azure-cosmosdb

解决方案


从评论跟进。

由于 db1 拥有所有客户的数据,物理分区将具有更多的 callTime 唯一值,因此为评估 callTime 而扫描的索引页数会很高。对于 db2,由于只有 1 个客户数据,因此逻辑分区和物理分区将是相同的。因此,虽然这不是扇出,但查询引擎仍需要在 callTime 上评估所有其他客户数据的范围过滤器。

要修复/提高 db1 的性能,您应该在 /ownerTime 和 /callTime 上创建一个复合索引,见下文。

"compositeIndexes":[
         [
            {
               "path":"/ownerTime"
            },
            {
               "path":"/callTime"
            }
         ]
    ],

谢谢。


推荐阅读