5.2 列族与存储参数设计


文档摘要

5.2 列族与存储参数设计:纵向的物理决策 本节摘要:列族是 HBase 的物理存储单位,建表时的参数组合(VERSIONS、TTL、COMPRESSION、BLOCKSIZE、BLOOMFILTER)决定这张表的磁盘形态与读写代价。本节逐参数给出决策依据与修改代价,并把"什么时候值得建第二个列族"这个高频问题讲透。 列族数量:默认一个,两个封顶 先重复 2.2 节的机制:每个列族一个 Store,Flush 时所有列族一起刷,每个 Store 各产一个 HFile——列族数直接放大 HDFS 写压力与小文件数量。再加 3.3 节的读视角:BlockCache 以块为单位缓存,访问模式不同的列族混在一行里,会互相污染缓存。

5.2 列族与存储参数设计:纵向的物理决策

本节摘要:列族是 HBase 的物理存储单位,建表时的参数组合(VERSIONS、TTL、COMPRESSION、BLOCKSIZE、BLOOMFILTER)决定这张表的磁盘形态与读写代价。本节逐参数给出决策依据与修改代价,并把"什么时候值得建第二个列族"这个高频问题讲透。

列族数量:默认一个,两个封顶

先重复 2.2 节的机制:每个列族一个 Store,Flush 时所有列族一起刷,每个 Store 各产一个 HFile——列族数直接放大 HDFS 写压力与小文件数量。再加 3.3 节的读视角:BlockCache 以块为单位缓存,访问模式不同的列族混在一行里,会互相污染缓存。

所以建第二个列族要过两道门:

  1. 读写模式确实不同:典型如订单表,cf 存高频读写的小字段(状态、金额),detail 存写一次读罕见的大字段(收货地址快照、发票明细)。分列族后扫 cf 不碰 detail 的存储,缓存也互不冲刷;
  2. 大小量级悬殊detail 若普遍几百 KB,混在 cf 的 64 KB 块里会严重拖累读放大。

反过来,字段访问模式一致就合用一个列族,把"语义区分"交给列限定符——列限定符不要钱(1.2 节:动态、免 DDL),列族很贵。极端反例是"一个字段一个列族",Flush 产物数量直接爆炸。

建表参数逐项决策

以订单表的完整建表语句为纲:

hbase:090:0> create 'orders', { hbase:091:1* NAME => 'cf', hbase:092:1* VERSIONS => '3', hbae:093:1* TTL => '15552000', -- 180 天 hbase:094:1* COMPRESSION => 'SNAPPY', hbase:095:1* BLOOMFILTER => 'ROW', hbase:096:1* BLOCKSIZE => '65536', hbase:097:1* BLOCKCACHE => true hbase:098:1* }, { hbase:099:1* NAME => 'detail', hbase:100:1* COMPRESSION => 'GZ', hbase:101:1* BLOCKSIZE => '262144', hbase:102:1* BLOOMFILTER => 'NONE' hbase:103:1* }

VERSIONS(默认 1)。保留几个历史版本。状态类字段保留 3 个便于审计"最近几次变更";不需要历史就留 1,读路径少做多版本合并(3.3 节)。配 MIN_VERSIONS 可与 TTL 组合:"过期但至少留 1 版"。

TTL(默认永久)。Cell 级过期,物理清除发生在 Major Compaction(2.3 节的伏笔)。按法规要求数据保留 180 天的场景,TTL 加定期 Major 是标准答案,比业务侧批量 delete 干净得多(墓碑本身也占地方)。

COMPRESSION(默认无)。SNAPPY 是均衡首选:压缩比约 2–3 倍,编解码快,CPU 换 IO 几乎稳赚。GZ 压缩比更高但慢,只配给"写一次读罕见"的冷列族(上例的 detail)。LZO/ZSTD 按集群可用性选。注意压缩作用于块(2.3 节),行键前缀重复的特性让 HBase 数据对压缩非常友好。

BLOCKSIZE(默认 64 KB)。读取块粒度,两难取舍:块大→索引少、顺序扫描快,但点查要解压更多无关数据,且缓存粒度粗;块小→点查快、缓存细,但索引膨胀、顺序扫描多付索引 IO。经验值:点查为主保持默认或 32 KB,顺序扫描为主(时序表)可到 128–256 KB。上例 detail 列族大块加 GZ,就是"冷数据大块吞"的配置。

BLOOMFILTER(默认 ROW)。行级布隆帮点查排除无关文件(原理与代价第 6 章展开)。行前缀布隆(ROWCOL 是列级,ROW_PREFIX 部分场景)按查询形态选;上例 detail 读罕见,索性 NONE 省内存。

IN_MEMORY(默认 false)。把列族优先留在缓存,维表、配置表这类小而热的表专用,慎用(挤占正常缓存)。

修改的代价:参数分三档

档位 参数 代价
可随时改 TTL、VERSIONS、COMPRESSION alter 即生效,后续 Compaction 逐步按新参数重写
改了要 Major BLOOMFILTER、BLOCKSIZE 只在新文件生效,要全面生效需 Major Compaction
基本改不动 列族名、行键 只能建新表迁移数据

这就是"Schema 定稿即锁定性能"的含义。建表前拿生产量级的模拟数据跑一轮基准(第 4.3 节的方法),比上线后 alter 补救便宜太多。改 TTL 有一个经典陷阱要单独点名:收紧 TTL 不会立刻腾空间,旧数据要等 Major 清理;而放宽 TTL 倒是立刻生效。容量规划别按错方向估。

⚠️ 常见坑:alter 操作会先让表 disable 再 enable(旧版本行为,2.x 部分参数在线改),生产高峰改表 = 自断业务。所有 alter 走变更流程:低峰、先快照、灰度验证。

用 describe 检查设计

设计定稿后自查一遍输出:

hbase:104:0> describe 'orders' orders COLUMN FAMILIES DESCRIPTION {NAME => 'cf', VERSIONS => '3', TTL => '15552000', COMPRESSION => 'SNAPPY', BLOOMFILTER => 'ROW', BLOCKSIZE => '65536', ...} {NAME => 'detail', VERSIONS => '1', COMPRESSION => 'GZ', BLOCKSIZE => '262144', ...}

对照四个问题:列族是否 ≤2?热冷是否分族?版本与 TTL 是否与数据生命周期一致?压缩与块大小是否与读写形态匹配?全过,Schema 的纵向部分就稳了。

💡 关键直觉:HBase 的"表结构"其实是一组物理存储参数而非数据约束——没有类型、没有非空约束、没有外键,数据质量责任全部上移到写入方。约束越少,参数决策越重。

本节要点回顾

  • 列族默认一个:过"读写模式不同、大小量级悬殊"两道门才建第二个;
  • 五参数口诀:版本按审计、TTL 按法规、压缩默认 SNAPPY、块大小按点查/扫描、布隆默认 ROW;
  • 修改分三档:轻参数随时改、块级参数要 Major、行键列族改不动;
  • TTL 收紧不腾空间:物理清除在 Major,容量规划按此估;
  • Schema 即物理:没有数据约束,只有存储决策,上线前用生产量级数据验一遍。

横向(5.1 行键)纵向(5.2 参数)都齐了,5.3 节把它们拼成两张真实生产表,并解决"一张表应付不了所有查询"的二级索引难题。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U