KES数据库存储管理深度解析

0 阅读7分钟

在这里插入图片描述

KingbaseES 在存储管理层面构建了一套完整的技术体系,涵盖超大字段处理、I/O 性能分层以及内存大页优化三大核心模块。下面从原理到实践,逐一拆解这三个关键机制。


一、TOAST 技术:超大字段的"压缩与分片"之道

1.1 为什么需要 TOAST?

KingbaseES 以**页(Page)**作为数据文件存储的基本单位,默认大小为 8KB,且严格禁止单行数据跨页存储。这意味着页大小就是行大小的硬上限。

当业务中出现 TEXTBYTEAJSONB 等大字段时,若不加处理,一行数据极易突破这一上限。TOAST(The Oversized-Attribute Storage Technique,超大属性存储技术)正是为此而生——通过压缩 + 切片行外存储两种手段,将超大字段"瘦身"后安全落盘,且对用户完全透明。


1.2 TOAST 的触发机制

阶段触发条件行为
压缩字段数据 > 2KB(TOAST_TUPLE_THRESHOLD优先对数据进行压缩
行外存储压缩后仍 > 2KB切片写入独立 TOAST 表,原字段替换为指针
不处理数据 ≤ 2KB直接存储在主表行内

每张主表都有一张唯一关联的 TOAST 表,命名规则为 pg_toast.pg_toast_<主表OID>,结构固定为三列:chunk_id(块标识)、chunk_seq(块序号)、chunk_data(实际数据)。


1.3 四种 TOAST 存储策略

PLAIN    → 禁止压缩 + 禁止行外存储(适用于 INTEGER 等定长类型)
EXTENDED → 允许压缩 + 允许行外存储(TEXT 等变长类型的默认策略)
EXTERNAL → 禁止压缩 + 允许行外存储(牺牲空间换取随机访问速度)
MAIN     → 允许压缩 + 禁止行外存储(尽量保留在主表行内)

查看与修改策略的方式:

-- 查看字段存储策略
\d+ tosttest

-- 修改为 EXTERNAL(禁止压缩,允许行外存储)
ALTER TABLE tosttest ALTER COLUMN name SET STORAGE EXTERNAL;

注意:修改 TOAST 策略不会影响已有数据的存储方式,仅对后续写入生效。


1.4 实验验证:EXTENDED vs EXTERNAL 的差异

以下实验直观展示了两种策略在行外存储时的本质区别:

EXTENDED 策略(先压缩,再行外存储):

name 字段长度达到 327,680 字节时,TOAST 表仅产生 2 行:
  chunk_seq=0 → 1988 字节
  chunk_seq=1 → 1781 字节
  合计约 3.7KB(原始数据经压缩后大幅缩小)

EXTERNAL 策略(禁止压缩,直接行外存储):

name 字段长度为 5,120 字节时,TOAST 表产生 3 行:
  chunk_seq=0 → 1988 字节
  chunk_seq=1 → 1988 字节
  chunk_seq=2 → 1144 字节
  合计 = 5120 字节(与原始数据完全一致,未压缩)

核心结论: EXTENDED 策略下,压缩优先于行外存储;一旦数据(压缩后)超过 2KB,无论哪种策略,均会触发行外存储。


二、逻辑读与物理读:I/O 性能的分层理解

2.1 KingbaseES 的内存区域划分

KingbaseES 的数据访问路径涉及三类内存区域,理解它们是分析 I/O 性能的基础:

内存区域作用可见范围
shared_buffers共享数据库块缓冲,所有关系表的读写必经之路所有会话共享
temp_buffers临时表专用缓冲仅当前会话可见
work_mem / maintenance_work_mem排序、Hash 等操作的工作内存,不足时溢出到临时文件仅当前会话可见

2.2 四种数据访问方式

Hit(逻辑读命中)  → 直接在 shared/local buffer 中找到数据,零磁盘 IO
Dirty(脏写)     → 数据写入内存缓冲区,尚未落盘
Read(物理读)    → 内存未命中,从操作系统缓存或磁盘读入内存
Written(物理写) → 从内存缓冲区写出到操作系统缓存或磁盘文件

2.3 通过 sys_stat_statements 量化 I/O

sys_stat_statements 视图是诊断 SQL 性能的核心工具,关键字段含义如下:

字段含义I/O 类型
shared_blks_hitshared_buffer 命中块数逻辑读(无 IO)
shared_blks_read从 OS 缓存/磁盘读入 shared_buffer 的块数物理读
shared_blks_written从 shared_buffer 写出的块数物理写
local_blks_read临时表缓冲未命中,从 OS 读入的块数物理读
temp_blks_read从临时文件读入 work_mem 的块数物理读(排序溢出)
temp_blks_written从 work_mem 写入临时文件的块数物理写(排序溢出)

与 Oracle 的重要区别: KingbaseES 的 read/written 统计包含操作系统缓存层,即使数据已在 OS Page Cache 中命中,也会被计入物理读,而 Oracle 的物理读统计不考虑 OS 缓存层。


2.4 性能诊断思路

逻辑读高(shared_blks_hit 大)  → 缓存利用率好,性能优
物理读高(shared_blks_read 大) → 缓存命中率低,考虑增大 shared_buffers 或优化索引
temp_blks 高                   → 排序/Hash 内存不足,考虑增大 work_mem

KWR 报告中的 TOP SQL 模块可直接定位高 I/O 消耗的 SQL 语句,是日常巡检的重要入口。


三、Hugepage 配置:锁定共享内存,告别 Swap

3.1 为什么要配置 Hugepage?

Linux 默认以 4KB 为单位管理内存,维护虚拟地址到物理地址映射的 Page Table 会随内存增大而急剧膨胀。对于 KingbaseES 这类需要大 shared_buffers 的数据库,开启 标准 Hugepage(2MB/页) 带来三重收益:

  • 降低 Page Table 开销:同等内存下,Hugepage 的页表条目数仅为普通页的 1/512
  • 锁定物理内存:Hugepage 预分配且不可被 Swap 换出,避免 shared_buffers 被置换到磁盘
  • 提升 TLB 命中率:更大的页面覆盖更多地址空间,减少 TLB Miss

透明大页(Transparent Hugepage)与标准大页同时存在时可能引发性能问题,强烈建议禁用透明大页。


3.2 标准 Hugepage 配置步骤

第一步:计算所需 Hugepage 数量

# 获取数据库主进程 PID
head -1 $KINGBASE_DATA/kingbase.pid

# 计算数据库共享内存占用(单位 KB)
pmap <PID> | awk '/rw-s/ && /zero/'
# 示例输出:400800K

# 查看系统 Hugepage 大小
grep ^Hugepagesize /proc/meminfo
# 示例输出:Hugepagesize: 2048 kB

# 计算所需页数:400800 / 2048 ≈ 196 页

第二步:分配并持久化 Hugepage

# 临时生效
sysctl -w vm.nr_hugepages=196

# 持久化配置
echo "vm.nr_hugepages = 196" >> /etc/sysctl.conf
sysctl -p

第三步:验证分配结果

cat /proc/meminfo | grep -i huge
# 关注:HugePages_Total=196,HugePages_Free=196

3.3 禁用透明大页

/etc/rc.local 中添加以下内容并重启:

if test -f /sys/kernel/mm/transparent_hugepage/enabled; then
    echo never > /sys/kernel/mm/transparent_hugepage/enabled
fi
if test -f /sys/kernel/mm/transparent_hugepage/defrag; then
    echo never > /sys/kernel/mm/transparent_hugepage/defrag
fi

3.4 配置数据库参数

kingbase.conf 中设置:

huge_pages = try   # 推荐:优先使用大页,不足时自动回退到普通页
# huge_pages = on  # 强制使用大页,大页不足则启动失败(生产环境谨慎使用)

验证是否生效: 重启数据库后,执行 pmap <新PID> | awk '/rw-s/ && /zero/',若无输出,则说明 Hugepage 已成功接管 shared_buffers 内存区域。


总结:三大机制的协同价值

这三项技术共同构成了 KingbaseES 存储管理的核心骨架:

技术解决的核心问题关键参数/阈值
TOAST超大字段突破 8KB 页限制TOAST_TUPLE_THRESHOLD = 2KB
逻辑读/物理读量化 SQL 的 I/O 消耗,定位性能瓶颈sys_stat_statements 视图
Hugepage锁定 shared_buffers,消除 Swap 风险huge_pages = try

三者从数据存储形态、I/O 行为分析、内存资源管理三个维度相互补充——TOAST 决定数据如何存,逻辑/物理读决定如何量化访问代价,Hugepage 则保障内存访问的稳定性与效率。掌握这三个机制,是深入理解 KingbaseES 性能调优的重要基础。

在这里插入图片描述