azure-cosmosdb - 两个数据库中的镜像数据产生截然不同的 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/*"
}
]
}
*更新:我最近用更清晰的查询更新了这个问题,并返回了查询统计信息。
解决方案
从评论跟进。
由于 db1 拥有所有客户的数据,物理分区将具有更多的 callTime 唯一值,因此为评估 callTime 而扫描的索引页数会很高。对于 db2,由于只有 1 个客户数据,因此逻辑分区和物理分区将是相同的。因此,虽然这不是扇出,但查询引擎仍需要在 callTime 上评估所有其他客户数据的范围过滤器。
要修复/提高 db1 的性能,您应该在 /ownerTime 和 /callTime 上创建一个复合索引,见下文。
"compositeIndexes":[
[
{
"path":"/ownerTime"
},
{
"path":"/callTime"
}
]
],
谢谢。
推荐阅读
- performance - 在 Docker 中覆盖 ENTRYPOINT 时停止 Apache2 的速度要慢得多
- excel - 如果列表中的值匹配,则在下面插入相应的值
- reactjs - React firebase 无法取消订阅监听器
- google-analytics - 谷歌分析不会在任何仪表板中显示任何数据
- recaptcha - 发布到不同服务器时的 Google recaptcha
- java - 有没有办法避免在 if else 块中重复方法调用?
- android-studio - 使用 Android Studio 4.0 创建布局检查器 *.li 文件
- laravel - Laravel - 如何在 Laravel 中删除空白
- selenium-webdriver - 当移动仿真和多个浏览器量角器/硒网络驱动程序时,为什么会出现“元素不可交互”?
- dynamics-365 - 如何访问 Dynamics 365 商业中心云服务的数据库?