当前位置: 首页 > news >正文

OBCP第三章 OceanBase SQL 引擎高级技术学习笔记

OceanBase SQL 引擎高级技术学习笔记

如不好理解可以看本人另一篇文章:
Oceanbase SQL 引擎高级技术学习笔记(通俗篇)

一、SQL 请求执行流程

缓存命中
缓存未命中
添加计划
SQL请求
Fast-parser
Plan Cache
Executor 执行器
Parser 词法/语法解析
Resolver 语义解析
Transformer 逻辑改写
Optimizer 优化器
Code Generator 代码生成
返回结果

1. 快速参数化(Fast-parser)

仅使用词法分析对文本串直接参数化,获取参数化后的文本及常量参数。

  • OBProxy路由决策
  • 快速参数化:常量变变量(@1, @2

2. 词法/语法解析(Parser)

在收到用户发送的 SQL 请求串后,Parser 会将字符串分成一个个的"单词",并根据预先设定好的语法规则解析整个请求,将 SQL请求字符串转换成带有语法结构信息的内存数据结构,称为语法树(Syntax Tree)。

  • 将SQL字符串拆分为单词流
  • 生成语法树(Syntax Tree)

场景:查询学生成绩

-- 原始SQL
SELECT name, score 
FROM students 
WHERE class = '3班' AND score > 90;
原始SQL文本
词法分析
Tokens:
SELECT, name, 逗号, score,
FROM, students,
WHERE, class, 等号, '3班',
AND, score, 大于号, 90
语法分析
语法树
SelectStmt
列列表
name
score
FROM students
WHERE条件
AND连接
class='3班'
score>90

========================================================

通俗理解:把客户的请求翻译为厨房认识的结构
给餐厅打电话点餐: “要 1 份宫保鸡丁 和 2 碗米饭”

厨师记录:

{"宫保鸡丁": { "数量": 1 },"米饭": { "数量": 2 }
}

3. 语义解析(Resolver)

  • 将语法树转换为语句树(Statement Tree)
  • 识别数据库对象(表、列、索引等)
  • 校验SQL语义正确性

============================================================

通俗理解:验证请求的合理性
厨师思考:
✅ 宫保鸡丁在菜单吗?
✅ 米饭是否可点?
❌ 想要"佛跳墙"但菜单没有 → 报错

抱歉,您点的"佛跳墙"不在菜单中
(错误代码 1146Table 'test.佛跳墙' doesn't exist)

技术要点:

检查表/列是否存在
验证权限:用户能否访问该表?
数据类型检查:不能把日期存到数字列

4. 逻辑改写(Transformer)

通俗理解:用更高效的方式实现相同结果
原需求:“做宫保鸡丁(要鸡肉)”
优化后:“用鸡胸肉代替整鸡(更快出餐)”

==============================================================

  • 基于规则的改写
    • 视图合并
    • 子查询展开
    • 外连接消除
    • LIMIT下压
  • 基于代价的改写
    • OR-Expansion(或展开)

5 优化器(Optimizer)

通俗理解:选择最佳执行策略
厨师决策:
👨🍳 方案A:用现成鸡胸肉(5分钟)
👩🍳 方案B:现切整鸡(15分钟)
→ 选择方案A

=========================================================

  • 生成最佳执行计划
  • 核心决策:
    • 访问路径选择(索引/全表扫描)
    • 连接顺序
    • 连接算法(Nested Loop/Hash/Merge Join)
    • 分布式计划并行优化

6. 代码生成器(Code Generator)

  • 将逻辑计划转换为可执行代码
  • 无优化决策,仅忠实翻译

通俗理解: 把优化方案转为可执行指令—>即:生成标准菜谱:
取300g鸡胸肉
油温180℃爆炒
加宫保酱汁翻炒

技术要点:

生成物理算子:IndexScan/HashJoin
确定并行度:开几个灶台同时做

7. 执行器(Executor)

  • 本地执行:从顶端算子逐层调用
  • 分布式执行
    • 拆分执行树为多个Job
    • 通过RPC分发到相关节点

通俗理解: 执行操作并返回结果–>即:厨师按菜谱操作:
单桌订单:自己完成
10桌宴席:分给帮厨并行做

8. 执行计划缓存(Plan Cache)

  • 避免重复优化,加速OLTP场景
  • 缓存键:参数化后的SQL文本
-- 查看计划缓存统计
SELECT * FROM v$plan_cache_plan_stat;

任务:
通俗理解: 避免重复优化–>餐厅记录:
订单A:宫保鸡丁+米饭 → 方案X(缓存在厨师脑子)
新订单:“同样来一份” → 直接按方案X做

管理机制:

场景处理方式
相同SQL再现直接复用计划
菜单更新(Schema变更)刷新缓存
内存不足(厨师脑容量不够)淘汰最少使用的计划 (最近没人点的菜)
-- 手动清除缓存(厨师忘记菜谱)
ALTER SYSTEM FLUSH PLAN CACHE;	

二、DML语句处理

1. INSERT执行计划

EXPLAIN INSERT INTO t1 VALUES(1,1),(2,2);
ID|OPERATOR   |NAME       |EST.ROWS
----------------------------------
0 | INSERT    |           |10
1 | EXPRESSION|           |10

2. UPDATE/DELETE执行计划

  • 优化器选择访问路径(索引/主表)
-- UPDATE使用索引扫描
EXPLAIN UPDATE t1 SET b=10 WHERE b=1;
ID|OPERATOR    |NAME        |EST.ROWS
------------------------------------
0 | UPDATE     |            |11
1 | TABLE SCAN |t1(idx1)    |36

3. 一致性校验

  • NOT NULL约束检查
  • UNIQUE KEY约束检查
  • 数据类型自动转换

4. 锁管理

  • 行级锁:无表锁,在线DDL不阻塞DML
  • 加锁顺序
    1. 数据表主键
    2. 本地索引
    3. 全局索引
  • 热点行优化
    SELECT ... FOR UPDATE; -- 显式加锁
    

三、DDL语句处理

流程特点

Client OBServer RootServer 所有节点 DDL请求 发送Schema变更 持久化Schema 异步刷新Schema Client OBServer RootServer 所有节点
  • 零阻塞:DDL不锁表,与DML并行
  • 全局一致性:RootServer统一调度
  • 自动记录格式:DML适配新Schema
    DDL

四、查询改写

查询改写(query rewrite):把一个 SQL 改写成另外一个更加容易优化的 SQL。

1. 基于规则的改写

改写类型作用
视图合并消除视图层,增加连接顺序选择
子查询展开转换为Semi/Anti-Join或内连接
外连接消除转换为内连接,优化连接顺序
LIMIT下压提前过滤减少处理量
子查询展开示例
-- 原始SQL
SELECT * FROM t1 WHERE t1.c1 IN (SELECT t2.c1 FROM t2);-- 改写为内连接(因t2.c1唯一)
SELECT t1.* FROM t1, t2 WHERE t1.c1 = t2.c1;

2. 基于代价的改写(OR-Expansion)

OceanBase 目前只一种支持基于代价的查询改写 - 或展开(Or-Expansion)(考点)

场景1:多索引加速
-- 原始SQL
SELECT * FROM t1 WHERE a=1 OR b=1;-- 改写后
SELECT * FROM t1 WHERE a=1
UNION ALL
SELECT * FROM t1 WHERE b=1 AND LNNVL(a=1);
场景2:避免笛卡尔积
-- 原始SQL(强制Nested Loop Join)
SELECT * FROM t1,t2 WHERE t1.a=t2.a OR t1.b=t2.b;-- 改写为Hash Join
SELECT * FROM t1,t2 WHERE t1.a=t2.a
UNION ALL
SELECT * FROM t1,t2 
WHERE t1.b=t2.b AND LNNVL(t1.a=t2.a);

五、执行计划分析

OceanBase 的优化器在生成连接顺序时主要考虑左深树的连接形式(考点)
执行计划
通过Explain命令查看优化器针对给定SQL生成的逻辑执行计划(考点)

1. EXPLAIN 输出解读

EXPLAIN SELECT * FROM t1,t2 WHERE t1.c1=t2.c1;
ID|OPERATOR      |NAME    |EST.ROWS
----------------------------------
0 | HASH JOIN    |        |1980
1 |─TABLE SCAN   |t1      |1000
2 |─TABLE SCAN   |t2      |1000
  • 算子(OPERATOR ) 类型
    • TABLE SCAN:表访问
    • HASH JOIN:哈希连接
    • SORT:排序
    • LIMIT:结果截取

2. 实时执行计划获取

-- 步骤1:查询plan_id
SELECT plan_id FROM v$plan_cache_plan_stat 
WHERE statement LIKE 'SELECT * FROM t%';-- 步骤2:查看物理执行计划
SELECT * FROM v$plan_cache_plan_explain
WHERE tenant_id=1001 AND plan_id=7; --当前版本,必须同时给定tenant_id和plan_id的值,否则系统将返回空集

3. SQL Trace 分析

通过SQL Trace查看执行过程信息及各阶段的耗时

SET ob_enable_trace_log=1;  -- 开启Trace
SELECT COUNT(*) FROM __all_table; -- 执行SQL
SHOW TRACE;  -- 查看各阶段耗时

六、执行计划缓存管理

1. 淘汰策略

参数作用默认值
ob_plan_cache_percentage计划缓存占租户内存比例10(%)
ob_plan_cache_evict_high触发淘汰的内存阈值90(%)
ob_plan_cache_evict_low停止淘汰的内存阈值50(%)

2. 手动操作

-- 清空当前节点计划缓存
ALTER SYSTEM FLUSH PLAN CACHE;-- 清空指定租户全局缓存
ALTER SYSTEM FLUSH PLAN CACHE tenant='tenant1' GLOBAL;

3. 使用控制

-- 会话级禁用计划缓存
SET ob_enable_plan_cache = FALSE;-- Hint强制不使用缓存
SELECT /*+ USE_PLAN_CACHE(NONE) */ * FROM t1;

最佳实践总结

  1. OLTP优化

    • 避免复杂子查询,优先使用JOIN
    • 利用计划缓存减少解析开销
  2. 索引设计

    • 为高频过滤条件创建索引
    • 组合索引遵循最左前缀原则(考点)
  3. 执行计划分析

    -- 逻辑计划分析
    EXPLAIN EXTENDED SELECT * FROM t1 WHERE c1=100;-- 物理计划验证
    SELECT * FROM v$plan_cache_plan_explain WHERE ...;
    
  4. 缓存管理

    -- 监控缓存命中率
    SELECT hit_count/(hit_count+slow_count) AS hit_ratio 
    FROM v$plan_cache_plan_stat;
    
http://www.lryc.cn/news/575334.html

相关文章:

  • Rust 中的 HTTP 请求利器:reqwest
  • 【STM32】端口复用和重映射
  • 一次性登录令牌(Login Ticket)生成机制分析
  • 环境太多?不好管理怎么办?TakMll 工具帮你快速切换和管理多语言、多版本情况下的版本切换。
  • 【Actix Web】Rust Web开发实战:Actix Web框架全面指南
  • 从零到一训练一个 0.6B 的 MoE 大语言模型
  • 百面Bert
  • 《网络攻防技术》《数据分析与挖掘》《网络体系结构与安全防护》这三个研究领域就业如何?
  • ASP.NET Core Web API 实现 JWT 身份验证
  • list类的详细讲解
  • 基于 Python 的批量文件重命名软件设计与实现
  • 二叉树理论基础
  • 【偏微分方程】基本概念
  • 逆向入门(8)汇编篇-rol指令的学习
  • 【kubernetes】--Service
  • 深入理解提示词工程:原理、分类与实战应用
  • 基于 opencv+yolov8+easyocr的车牌追踪识别
  • linux-修改文件命令(补充)
  • Windows 安装 Redis8.0.2
  • 多传感器标定简介
  • day042-负载均衡与web集群搭建
  • python3虚拟机线程切换过程
  • 定位坐标系深度研究报告
  • LangGraph--基础学习(Human-in-the-loop 人工参与深入学习2)
  • 达梦数据库安装
  • 深入理解Redis
  • 【深度学习新浪潮】什么是上下文工程?
  • Introduction to Software Engineering(TE)
  • Linux 怎么恢复sshd.service
  • 【C++】std::function是什么