数据库接口与表缓冲 (★★)
#open-sql #database #table-buffer
架构概述
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| +-------------------+ | ABAP 程序 | +--------+----------+ | Open SQL / Native SQL +--------v----------+ | 数据库接口 | | + Open SQL 解析器| | + 表缓冲 | | + 游标缓存 | | + Native SQL 接口| +--------+----------+ | +--------v----------+ | 数据库 | +-------------------+
|
| 组件 |
作用 |
| Open SQL 解析器 |
检查语法,转换为数据库特定 SQL |
| Native SQL 接口 |
将 Native SQL 直接传递给数据库 |
| 表缓冲 |
应用服务器上的本地缓存 |
| 游标缓存 |
复用已解析/已准备好的游标 |
SAP 表缓冲 vs 数据库缓冲
| 方面 |
SAP 表缓冲 |
数据库缓冲 |
| 位置 |
应用服务器(共享内存) |
数据库服务器 |
| 管理者 |
SAP 内核 / 数据库接口 |
DBMS 本身 |
| 目的 |
完全避免数据库往返 |
在 RAM 中缓存磁盘块 |
| 范围 |
系统中所有应用服务器 |
单个数据库服务器 |
缓冲类型
| 类型 |
使用场景 |
行为 |
| 完全缓冲 |
小表,很少更改 |
首次访问时加载整个表 |
| 泛型缓冲 |
按泛型键(部分键)访问 |
加载匹配泛型键的记录 |
| 单条记录缓冲 |
仅按完整键访问 |
按需加载单条记录 |
1 2 3
| 完全: SELECT * FROM buffered_tab → 一次加载整个表 泛型: SELECT * FROM tab WHERE key1 = 'A' → 加载所有 'A*' 记录 单条: SELECT * FROM tab WHERE key1='A' AND key2='01' → 加载一条记录
|
缓冲同步
- 当记录被更改时,所有应用服务器上的缓冲条目被失效
- 失效使用同步表,定期检查
- 跨服务器的更改和缓冲失效之间可能有延迟
BYPASSING BUFFER 强制直接从数据库读取
缓冲绕过触发条件
当 SELECT 使用以下内容时,SAP 表缓冲被绕过:
| 绕过条件 |
示例 |
JOIN |
SELECT ... FROM a JOIN b ... |
| 子查询 |
WHERE col IN (SELECT ...) |
| 聚合函数 |
SUM()、COUNT()、AVG() 等 |
ORDER BY |
按非键字段排序 |
GROUP BY |
分组结果 |
DISTINCT |
去重 |
数据库索引
| 索引类型 |
描述 |
| 主索引 |
从主键字段自动创建 |
| 次索引 |
在 ABAP 字典中定义的替代访问路径 |
- 优化器根据 WHERE 子句确定使用哪个索引
- 选择良好的次索引可大幅提升读取性能
| 索引过多会减慢 INSERT/UPDATE/DELETE |
1 2 3 4 5 6
| 表:SPFLI 主索引: MANDT + CARRID + CONNID 次索引: MANDT + CITYFROM + CITYTO (用于路线查找)
SELECT ... WHERE carrid = 'LH' AND connid = '0400' → 主索引 SELECT ... WHERE cityfrom = 'NYC' AND cityto = 'SFO' → 次索引
|
考试/测试模式
| 关键词 / 短语 |
答案 |
| “什么会绕过表缓冲?” |
JOIN、子查询、聚合函数、ORDER BY、GROUP BY、DISTINCT |
| “完全缓冲何时加载?” |
首次访问时加载整个表 |
| “泛型缓冲使用什么?” |
部分键(泛型键字段) |
| “缓冲失效机制?” |
更改的记录通过同步表在所有应用服务器上触发失效 |
| “谁决定访问策略?” |
数据库优化器 |
| “主索引由什么组成?” |
主键字段(加上客户端) |
相关笔记