使用 obdiag 评估预建索引空间大小

1. 背景


最开始不过是一次平淡无奇的报错4184 - Server out of disk space,一次社区问题的讨论:  新建索引空间膨胀问题 ,一个新功能特性的诞生:  obdiag 索引空间预估 ,直到有机会在这里和大家讨论学习。OceanBase 索引磁盘空间放大问题究其根因是其存储引擎是基于 LSM-Tree 架构实现的,LSM-Tree 的设计理念是将随机写操作转化为顺序写操作,从而提高写入性能。其实现是采用分层的方式,即数据先追加写到日志,再写入内存,内存分为可写与只读两部分,通过冻结可写部分来生成只读部分,通过将只读部分下刷到磁盘形成持久化只读数据,如下图所示。

1724911141

正是因为这种分层的结构特点,会存在大量冗余和无效数据占用额外的存储,放大了磁盘空间。而 OceanBase 也在权衡读放大、写放大和空间放大问题上不断迭代优化,4.2.3 版本也已经将空间膨胀系数从 5.5 缩小到了 1.5,下文会用到这个系数预估索引空间大小。下面介绍一下如何预估索引空间大小。

2. 手动预估索引空间大小


如下步骤是在 sys 租户下执行的

2.1 根据租户名获取 tenant_id

select
  tenant_idfrom
  __all_tenantwhere
  tenant_name = '租户名';

2.2 根据表名获取 table_id

select
  table_idfrom
  __all_virtual_tablewhere
  table_name = '表名'
  and tenant_id = '租户id';

2.3 根据表名获取表的空间大小

select
  svr_ip,
  svr_port,
  sum(original_size) as estimated_table_sizefrom
  __all_virtual_tablet_sstable_macro_infowhere
  tablet_id in (
    select
      tablet_id    from
      __all_virtual_tablet_to_table_history    where
      tenant_id = '租户id'
      and table_id = '表id'
  )
  and (svr_ip, svr_port) in (
    select
      svr_ip,
      svr_port    from
      __all_virtual_ls_meta_table    where
      role = 1
  )group by
  svr_ip,
  svr_port;

2.4 查询预估表所有列的长度之和

select
  table_id,
  sum(data_length) as all_columns_lengthfrom
  __all_virtual_column_historywhere
  tenant_id = 'table_id'
  and table_id = 'table_id';

2.5 查询预创建索引的列长度之和

select
  table_id,
  sum(data_length) as index_columns_lengthfrom
  __all_virtual_column_historywhere
  tenant_id = 'table_id'
  and table_id = 'table_id'
  and column_name in('name1','name2');

2.6 根据OB不同版本的膨胀系数计算索引占用的空间大小

# 计算索引列的空间大小estimiated_index_size = (index_columns_length / all_columns_length) * estimated_table_size# 根据膨胀系数估算索引最终占用的磁盘空间大小(4.2.3及之后的版本的放大系数是1.5,之前的为5.5)observer_version >= 4.2.3 ? 1.5 * estimated_index_size : 5.5 * estimated_index_size

3. 使用 obdiag 预估索引空间大小


处理故障时如果想估算一下索引磁盘空间大小,会被手动繁琐的步骤消耗比较多的时间,obdiag 可以用一条命令搞定。

3.1 示例

# obdiag analyze index_space --tenant_name=test1 --table_name=table1 --column_names=name,addr
analyze_index_space start ...
start query estimated_table_data_size, please wait some minutes... ok
+---------------------------------------------------------------------+
|                    estimated-index-space-report                     |
+---------- ----+------+-----------------------+----------------------+
|      ip       | port | estimated_index_space | available_disk_space |
+--------- -----+------+-----------------------+----------------------+
| 192.168.1.190 | 2882 |        68.41 MB       |       55.09 GB       |
| 192.168.1.191 | 2882 |        68.41 MB       |       55.00 GB       |
| 192.168.1.192 | 2882 |        68.41 MB       |       55.11 GB       |
+---------------+------+-----------------------+----------------------+
Trace ID: c723baec-6391-11ef-9c0c-000c2934fb31
If you want to view detailed obdiag logs, please run: main.py display-trace c723baec-6391-11ef-9c0c-000c2934fb31

3.2 查看帮助

索引磁盘空间估算是 obdiag 的一键分析场景下的功能,通过 --help 查看帮助信息。

# obdiag analyze index_space --help
Usage: main.py analyze index_space [options]
Options:
  --inner_config=INNER_CONFIG
                        change inner config.
  --tenant_name=TENANT_NAME
                        tenant name
  --table_name=TABLE_NAME
                        table name
  --index_name=INDEX_NAME
                        specify the index name if an index already exists in
                        the table
  --column_names=COLUMN_NAMES
                        specify the column names of index that have not been
                        created yet;eg:--column_names=c1,c2,c3
  -c C                  obdiag custom config
  --config=CONFIG       config options Format: --config key=value
  -h, --help            Show help and exit.
  -v, --verbose         Activate verbose output.

3.3 功能场景

目前 analyze 场景的 index_space 功能支持两种场景,一种是索引还未创建,通过将要创建的索引列来分析磁盘空间占用;另一种是分析已存在索引的空间大小。

第一种功能场景在 3.1示例中已经展示,下面展示下第二种场景,只需要将 --column_names 参数替换为 --index_name 即可。

注意:如果两个参数同时存在,将会只分析 --index_name 参数中已存在的索引。

# obdiag main.py analyze index_space --tenant_name=test1 --table_name=table1 --index_name=index1
analyze_index_space start ...
start query estimated_table_data_size, please wait some minutes... ok
+---------------------------------------------------------------------+
|                    estimated-index-space-report                     |
+---------------+------+-----------------------+----------------------+
|      ip       | port | estimated_index_space | available_disk_space |
+---------------+------+-----------------------+----------------------+
| 192.168.1.190 | 2882 |        68.41 MB       |       54.95 GB       |
| 192.168.1.191 | 2882 |        68.41 MB       |       54.81 GB       |
| 192.168.1.192 | 2882 |        68.41 MB       |       54.91 GB       |
+---------------+------+-----------------------+----------------------+
Trace ID: ea61b078-661f-11ef-8869-000c2934fb31
If you want to view detailed obdiag logs, please run: main.py display-trace ea61b078-661f-11ef-8869-000c2934fb31

4. obdiag 贡献代码生命周期


obdiag 开源社区非常欢迎小伙伴参与共建,下面以给 obdiag 贡献功能代码《预估索引空间大小》为例,介绍一下贡献代码的生命周期。

4.1 需求提出

需求的提出有多种形式,或是起初功能路线的规划需求,或是实践过程中使用者提出的使用方法及体验需求,或是社区在 GitHub 上贡献的 issue等等。

预估索引空间大小是在 GitHub issue 提出的需求:  [Feature]: 支持在创建索引前评估待创建的索引大小

1725157048

4.2 需求分析

该功能主要是获取索引列的空间占用,通过 OceanBase 底层字典表进行统计即可,详细过程可参见第 2 章节手动预估索引空间大小。

4.3 设计方案

4.3.1 标题

《obdiag 评估预创建索引大小》

编号 文档版本 修订章节 修订原因 修订日期 修订人
1 0.1
初稿 2024-08-15 xxx

4.3.2 需求背景

4.3.3 功能性设计

4.3.3.1 功能流程图

1725167720

4.3.3.2 命令选项

obdiag analyze index_space --tenant_name=test1 ---table_name=table1 [--index_name=xx] [--column_names=c1,c2,c3]

4.3.3.3 详细步骤流程

详见第 2 章节手动预估索引空间大小,这里就不重复描述了。

4.3.4 非功能性设计

4.3.4.1 安全

暂未涉及

4.3.4.2 文档

文档补充:  索引空间分析使用说明

4.3.5 影响评估

4.3.5.1 兼容性评估

命令行参数兼容 json 和 key-value 两种格式。

4.3.5.2 风险评估

暂无风险

4.3.5.3 性能评估

暂无

4.3.6 测试分析

详见下文:4.4提测

4.3.7 工作量评估

4.3.7.1 任务拆解

4.3.7.2 开发计划

4.4 提测

4.4.1 标题

《obdiag 提测文档-评估预创建索引大小》

编号 文档版本 修订章节 修订原因 修订日期 修订人
1 0.1
初稿 2024-08-26 xxx

4.4.2 文档链接

4.4.3 提测范围

  • 基于索引名称估算索引大小/python3 main.py analyze index_space --tenant_name=CHAT_BI --table_name=t555 --index_name=k1
  • 基于列名预估算索引大小/python3 main.py analyze index_space --tenant_name=CHAT_BI --table_name=t555 --column_names=name,addr

4.4.4 影响范围

无影响。

4.4.5 验收状态

  • 无需验收
  • 已验收
  • 未验收

4.4.6 测试项目

测试项目 项目编号 测试内容 测试步骤 期望结果
评估预创建索引大小 1 预估索引大小 CREATE TABLE `t555` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(100) DEFAULT NULL, `age` int(11) DEFAULT '19', `addr` varchar(200) DEFAULT 'beijing', KEY `k1` (`id`), KEY `k2` (`name`, `addr`)); 正确输出索引大小

4.4.7 自测记录

项目编号 用例编号 测试步骤 预期结果 测试信息 测试结果 测试人 版本
1 1 python3 main.py analyze index_space --tenant_name=CHAT_BI --table_name=t555 --index_name=k1 1725268352



1 2 python3 main.py analyze index_space --tenant_name=CHAT_BI --table_name=t555 --column_names=name,addr 1725268358



4.4.8 文档

文档:  索引空间分析使用说明

4.4.9 附录

4.4 需求上线

在 GitHub 上提交新功能 PR,并和社区维护者讨论修改,如果没问题就可以被 Committer 或 Maintainer 提交完成贡献了。

附上该功能的PR:  add analyze index space feature #393

1725330488

参考文章

一个存储引擎的“水生态”|OceanBase 转储合并技术原理(一)

与传统LSM-Tree结构的异同 | OceanBase 存储引擎技术原理(二)

obdiag SIG


请使用浏览器的分享功能分享到微信等