- 最新动态
- 功能总览
-
服务公告
- 漏洞公告
-
产品公告
- 【通知】2024年11月5日起文档数据库服务DDS5.0版本集群开放公测
- 【通知】2024年10月11日起文档数据库服务DDS副本集5.0版本开始转商计费
- 【通知】华为云文档数据库服务DDS3.4版本计划于2024年10月11日停售
- 【通知】2024年07月24日起文档数据库服务DDS5.0版本开放公测
- 【通知】2023年02月15日起文档数据库服务上线x86架构增强Ⅱ型副本集和集群shard的1:8系列规格
- 【通知】文档数据库服务DDS4.4邀请公测
- 【停售公告】华为云文档数据库服务DDS单节点规格计划于2023年07月15日停售内部通知
- 【通知】2023年10月8日起文档数据库服务DDS4.4版本开始转商计费
- 版本说明
- 产品发布说明
- 产品介绍
- 计费说明
- 快速入门
- 开发指南
-
用户指南
- 购买实例
- 连接实例
- 数据迁移
- 性能调优
- 权限管理
- 实例生命周期管理
- 变更实例
- 数据备份
- 数据恢复
- 参数模板管理
- 连接管理
- 数据库使用
- 数据安全性
- 监控与告警
- 审计
- 日志管理
- 任务中心
- 智能DBA助手
- SQL自动查杀
- 跨可用区容灾
- 标签管理
- 配额管理
- DDS使用规范建议
-
最佳实践
- DDS最佳实践汇总
- 安全最佳实践
- 连接DDS实例的常用方式
- 其他云MongoDB迁移到DDS
- 本地MongoDB迁移到DDS
- ECS自建MongoDB迁移DDS
- 如何实现副本集高可用和读写分离
- 通过设置数据分片提升性能
- 如何通过SQL优化来提升DDS性能
- 如何规避dds mongos路由缓存缺陷
- 排查DDS实例CPU使用率高的问题
- 排查DDS实例内存占用较高的问题
- 排查DDS实例连接数耗尽的问题
- 创建用户并授权使用DDS只读权限
- 合理使用DDL(Data Definition Languages)语句
- DDS节点脱节原理和说明
- 避免hideIndex导致游标失效
- 使用DDS存储和分析日志数据
- DDS查询计划及查询重规划
- 安全白皮书
- 性能白皮书
-
API参考
- 使用前必读
- API概览
- 如何调用API
- 快速入门
-
API v3(推荐)
- 查询API版本
- 查询数据库版本信息
- 查询数据库规格
- 查询数据库磁盘类型
-
实例管理
- 创建实例
- 重启实例
- 删除实例
- 查询实例列表和详情
- 扩容实例存储容量
- 扩容集群实例的节点数量
- 变更实例规格
- 切换副本集实例的主备节点
- 切换SSL开关
- 修改实例名称
- 修改实例备注
- 修改数据库端口
- 变更实例安全组
- 绑定弹性公网IP
- 解绑弹性公网IP
- 修改实例内网地址
- 创建集群的Shard/Config IP
- 副本集跨网段访问配置
- 查询实例可迁移到的可用区
- 实例可用区迁移
- 设置实例回收站策略
- 扩容副本集实例的节点数量
- 实例新增只读节点
- 数据库补丁升级
- 开启/关闭秒级监控
- 查询秒级监控配置
- 设置可维护时间段
- 查询实例回收站策略
- 查询回收站实例列表
- 检查弱密码
- 查询数据库补丁升级预估时长
- 查询实例磁盘信息
- 获取SSL证书下载地址
- 查询数据库复制集名称
- 修改数据库复制集名称
- 删除实例的节点
- 删除实例的只读节点
- 查询副本集跨网段访问配置
- 查询LTS日志配置信息
- 关联LTS日志流
- 解除关联LTS日志流
- 设置磁盘自动扩容策略
- 查询磁盘自动扩容策略
- 批量数据库补丁升级
- 连接管理
- 备份与恢复
- 参数配置
- 获取日志信息
- 标签管理
- 管理数据库和用户
- 配额管理
- 数据库运维
- 任务管理
- API v3(即将下线)
- 应用示例
- 权限策略和授权项
- 附录
- SDK参考
- 场景代码示例
- 常见问题
-
故障排除
- 概述
- DDS实例节点故障处理机制
- 连接失败,提示:network error while attempting to run command ‘isMaster’
- 连接失败,提示:No route to host以及connection attempt failed
- 连接失败,提示:Authentication failed
- 连接失败,提示:couldn't connect to server
- 连接失败,提示:cannot list multiple servers in URL without ‘replicaSet’ option
- Java驱动连接实例失败,提示:Timeout while receiving message
- 连接失败,提示:exception: login failed 以及 U_STRINGPREP_PROHIBITED_ERROR
- 视频帮助
- 文档下载
- 通用参考
链接复制成功!
DDS查询计划及查询重规划
DDS查询计划是决定查询如何执行的详细过程。DDS查询优化器会根据查询的条件、数据分布、索引信息等选择一个执行计划,以确保查询的执行效率。然而,在某些情况下,DDS会重新评估并生成新的查询计划,即查询重规划。用户理解何时发生查询重规划以及如何应对这一过程,这将有助于提升数据库性能并有效减少资源浪费。
以下将介绍DDS查询计划的工作原理,查询重规划的触发场景,以及处理和优化查询重规划的最佳实践。
查询计划的概述
查询计划是在执行查询时,DDS查询优化器选择的执行路径。这个执行路径定义了如何扫描数据,是否使用索引,以及如何处理查询的每个阶段。DDS通过以下几个步骤生成查询计划:
- 解析查询:DDS解析查询条件,识别字段和操作符。
- 选择索引:基于查询的条件,DDS会检查可用的索引,并选择最适合的索引来加速查询。
- 评估执行路径:DDS会基于数据量、字段选择性、索引类型等评估可能的执行路径,最终选择最优的执行路径生成新的查询计划。
- 执行查询:DDS按照选定的查询计划执行查询并返回结果。
查询重规划的概述
查询重规划(Query Re-Planning)是指DDS在执行查询过程中,基于数据变化或查询结构的变化,重新评估并生成一个新的查询计划。查询重规划发生时,DDS会放弃之前选择的查询计划,采用新的执行路径。
查询重规划的主要目的是在数据环境变化时,确保查询能够适应新的数据分布、索引变化和负载变化,从而维持查询性能的稳定。
查询重规划的触发场景
以下是一些常见的查询重规划场景:
- 索引变化
新增或删除索引:当某个字段的索引发生变化(如新增索引或删除索引)时,DDS可能会重新规划查询执行计划。查询可能会重新评估现有索引的有效性,进而选择新的索引,或决定使用全表扫描。
- 数据分布变化
如果数据分布发生了变化(例如某个字段的选择性发生显著变化),DDS可能会重新评估查询计划,以确保选择最佳的执行路径。例如,某个字段变得更加稀疏或密集,导致索引的效益变化。
- 查询条件变化
当查询条件变化时,DDS可能需要重新生成查询计划。例如,某些查询添加了新的筛选条件,或者查询条件中使用了不同的操作符(如从$eq改为$in)。
- 聚合管道中的变化
在聚合操作中,如果数据量、字段或管道顺序发生变化,DDS可能会重新评估聚合管道的执行计划。尤其是当管道阶段的数据过滤条件发生变化时,DDS可能会重新选择执行路径。
- 环境资源压力变化
在实例负载发生变化(如节点资源耗尽、硬盘空间不足、或网络延迟增加)时,DDS可能会重新调整查询计划,以便在当前资源条件下优化查询性能。
- 查询缓存失效
DDS会将之前执行的最优的查询计划缓存,DDS在某些情况下可能会使用查询缓存。随着查询缓存的失效,查询计划可能会被重新生成。
查询重规划的影响
发生重规划时,会在慢日志中看到关键字:replanned:1,这表示数据库无法针对当前查询模式的查询条件提供始终有效的计划。
频繁的查询重新规划(Query Re-Planning)可能带来以下影响:
- CPU开销增加:频繁的重新规划会消耗更多CPU资源,影响整体性能。
- 内存消耗增加:频繁重新规划会增加内存使用,可能影响其他操作。
- 查询延迟增加:每次重新规划都会增加查询执行时间,导致响应变慢。
查询重规划的处理建议
- 定期监控查询计划
建议定期监控查询的执行计划,特别是在系统发生变动后,如添加索引、新增数据或调整查询结构。通过以下方式实现:
- 使用explain()方法分析查询的执行计划。
- 定期检查慢日志,了解可能的查询计划变化。
- 观察查询计划变化的原因
当查询重规划发生时,首先要确定是哪些因素导致了查询计划的变化。根据以下几个方面进行排查:
- 索引变化:使用db.collection.getIndexes()检查现有索引,确认是否有索引的新增或删除。
- 数据分布:通过统计信息来检查数据是否发生了显著变化。例如使用db.collection.stats()查看集合的统计信息,如文档数、数据大小和索引大小。
- 查询条件:检查查询条件是否发生了变化,是否增加了新的字段或者修改了查询操作符。
- 针对查询重规划进行优化
- 【推荐】确保数据库环境有足够的资源(CPU、内存、磁盘等)来处理负载,减少因资源限制导致的查询重规划,升级实例规格以缓解数据库负载压力,具体操作请参考文档变更实例的CPU和内存规格。
- 【推荐】预估数据分布:在设计索引时,可以使用数据分布的预测来选择合适的字段进行索引,以避免数据分布变化时引发频繁的查询重规划。
- 【推荐】使用稳定的索引:确保为常用查询提供稳定且合适的索引。特别是在数据量较大时,索引可以有效减少查询重规划的发生。
- 【推荐】尽量避免频繁变化的查询结构:查询条件的频繁变动可能会导致DDS经常重新生成查询计划。建议根据业务需求,尽量确保查询条件的一致性。
- 【推荐】聚合优化:如果您的查询涉及复杂的聚合管道,建议定期分析管道的执行计划并进行优化。可以通过$match在聚合管道的早期阶段过滤数据,减少后续阶段的数据处理量。
- 对发生replan的查询条件使用hint()来指定索引,对查询调用此方法可覆盖DDS的默认索引选择和查询优化过程。示例:
db.users.find({gender:"M"},{user_name:1,_id:0}).hint({gender:1,user_name:1})
- 在发生replan的查询条件使用索引过滤器来限制使用的索引,索引过滤器会覆盖查询计划器正常选择查询计划的行为,当一个查询同时存在Hint和索引过滤器时,索引过滤器会覆盖指定的Hint值,因此,您应当谨慎使用索引过滤器。以下示例为orders集合创建了一个索引筛选器。该筛选器适用于其谓词为item字段的等值匹配的查询,其中仅投影quantity字段,并指定按order_date升序排序。
db.runCommand( { planCacheSetFilter: "orders", query: { item: "ABC" }, projection: { quantity: 1, _id: 0 }, sort: { order_date: 1 }, indexes: [ { item: 1, order_date: 1 , quantity: 1 } ] } )
对于计划缓存查询结构,查询优化器将仅考虑使用索引{ item: 1, order_date: 1, quantity: 1 }的索引计划。
评估重规划并采取措施
查询重规划可能会导致执行计划的变化,进而影响查询的性能。在重规划发生时,需要评估查询性能的变化,检查是否有提升或下降,并相应地采取措施:
- 性能下降:如果发现查询性能因查询重规划而下降,可以通过添加或调整索引来改善性能。
- 性能提升:如果重规划后的查询执行更高效,可以继续保持当前的执行计划,监控是否有其他潜在的性能瓶颈。