查询优化器介绍
一句话定义
Doris 查询优化器(Nereids)是基于 Cascades 框架构建的现代化查询优化器,通过 RBO(基于规则的优化)与 CBO(基于成本的优化)相结合,为复杂查询生成高效的执行计划。
阅读速览
在阅读本文前,建议先了解以下内容:
- 查询优化器在数据库系统中的基本作用
- SQL 执行计划的基本概念
- 基于规则优化(RBO)与基于代价优化(CBO)的区别
本文将依次介绍:
- 查询优化器的研发背景
- Doris 查询优化器的核心优势
- 优化器的整体工作原理
- 常用调优会话变量
研发背景
当前的查询优化器面临三类挑战:
| 挑战 | 具体表现 |
|---|---|
| 查询复杂度高 | 用户的查询语句日益复杂,查询场景日益多样化 |
| 实时性要求严 | 用户期望即时获取查询结果 |
| 迭代速度快 | 需要快速适配不断出现的新需求 |
基于以上背景,Doris 启动了全新查询优化器的研发。该优化器依托现代优化器架构,旨在更高效地处理 Doris 场景下的查询请求,并为未来更复杂的需求提供良好的扩展基础。
Doris 查询优化器优势
Doris 查询优化器在「智能、稳定、灵活」三个维度上相较于旧优化器具备显著优势。
更聪明
- 优化器将每个 RBO 与 CBO 的优化点以「规则」的形式清晰呈现。
- 每条规则都提供了一组用于描述查询计划形状的模式,能够精确匹配可优化的查询计划。
- 因此,优化器能够更好地支持多层子查询嵌套等复杂查询语句。
CBO 部分基于先进的 Cascades 框架,充分利用以下三类信息:
- 丰富的数据统计信息
- 数据特征信息
- 精心调优的代价模型
借助这些信息,优化器在处理多表 Join 等复杂查询时能够游刃有余。
更稳定
- 所有优化规则均在逻辑执行计划树上完成。
- 查询语法语义解析完成后,会被转换为树状结构。
- 相比旧优化器,新优化器的内部数据结构更加合理、统一。
以子查询处理为例:新优化器基于新的数据结构,避免了旧优化器中众多规则对子查询的单独处理,从而降低了优化规则出现逻辑错误的可能性。
更灵活
优化器的架构设计合理且现代,扩展优化规则与处理阶段非常方便,能够快速增加新功能以满足不断变化的需求。
优化器工作原理
整体流程

优化器的执行流程大致分为以下四个步骤:
| 步骤 | 阶段 | 说明 |
|---|---|---|
| 1 | 语法分析 | 将 SQL 文本转换为抽象语法树(AST)。SQL 合法则继续,非法则报错并终止 |
| 2 | 语义分析 | 检查 AST 中表、列、函数等的存在性以及使用是否符合语法和语义规则。合法则继续,非法则报错并终止 |
| 3 | 改写查询计划(RBO) | 通过预定义的规则对查询计划进行改写,常见手段包括列裁剪、谓词下推、分区裁剪等 |
| 4 | 优化查询计划(CBO) | 在搜索空间中枚举等价的计划集合,评估各计划的执行代价,选择代价最小的计划作为最终执行计划 |
各步骤的目标如下:
- 语法分析:确保 SQL 文本可被解析为合法的 AST。
- 语义分析:确保 AST 中引用的对象存在且使用方式合法。
- RBO 改写:通过确定性规则优化执行速度。
- CBO 优化:基于代价模型选择最优执行计划,确保查询以最高效的方式执行。
常用会话变量
nereids_timeout_second
| 项 | 内容 |
|---|---|
| 作用 | 设置查询规划的最大允许时间。规划时间超过该值时,规划将被终止并返回错误信息 |
| 默认值 | 30s |
| 适用场景 | 查询涉及大量外部表,或查询语句特别复杂时,可适当增加该值以确保查询正常进行 |
设计目的:在规划查询语句的过程中,系统会获取 SQL 涉及的所有表的读锁。设置超时机制的主要目的是:
- 维护集群的稳定性
- 防止规划时间过长造成资源过度占用
- 避免锁冲突问题
调优建议:
- 当出现规划超时错误时,先排查 SQL 是否过于复杂或表数量过多。
- 如确认是合理场景,可通过
SET nereids_timeout_second = <秒数>;调大该值。