首先为大家推荐这个 OceanBase 开源负责人老纪的公众号 "老纪的技术唠嗑局",会持续更新和 #数据库 、#AI 、#技术架构 相关的各种技术内容。欢迎感兴趣的朋友们关注!
这是一篇纯运维向的文章。献给所有正在了解 OB,以及准备对 OB 进行测试的朋友们。
背景
准备对 OceanBase 进行测试的朋友们,一定会测一下这款数据库的高压缩比是否如官网上所说的这么恐怖。
目前,在 OceanBase 官网上,虽然已经有 999+ 个与 "磁盘占用空间" 相关的官方文档,但依然无法阻碍用户在 OceanBase 社区论坛中提出 999+ 个与 "磁盘占用空间" 相关的问题。

为了减轻 OceanBase 社区论坛值班同学的工作量,今天简单整理了一篇与 "磁盘占用空间" 相关的文章,在这里和大家分享。欢迎大家在留言区评论、吐槽,以及合理地对作者进行谩骂。
注意:
下文中出现的命令,需要通过 sys 租户,在 oceanbase 库中执行。
文中可能会不厌其烦地备注,希望读者朋友们能够宽恕我的啰嗦。
查询集群和节点的磁盘空间
使用 sys 租户,在 oceanbase 库中,查询各个节点的磁盘占用:
sql
SELECT
SVR_IP,
DATA_DISK_IN_USE / 1024 / 1024 / 1024 AS USED_GB
FROM oceanbase.gv$ob_servers;
+--------------+----------------+
| SVR_IP | USED_GB |
+--------------+----------------+
| 12.345.67.89 | 0.300781250000 |
+--------------+----------------+
1 row in set (0.02 sec)
查询租户的的磁盘空间
使用 sys 租户,在 oceanbase 库中,查询指定租户的磁盘占用。需要在 SQL 中填写 tenant_id = xxx:
sql
SELECT svr_ip,
svr_port,
tenant_id,
sum(used_size) / 1024 / 1024 / 1024 AS used_gb
FROM oceanbase.__all_space_usage
WHERE tenant_id = xxx
AND file_type IN ('tenant file data',
'tenant meta data',
'tenant tmp data')
GROUP BY svr_ip,
svr_port;
+--------------+----------+-----------+----------------+
| svr_ip | svr_port | tenant_id | used_gb |
+--------------+----------+-----------+----------------+
| 12.345.67.89 | 22602 | 1002 | 0.026878356934 |
+--------------+----------+-----------+----------------+
查询 DataBase 的的磁盘空间
使用 sys 租户,在 oceanbase 库中,查询指定 database 的磁盘占用。需要在 SQL 中填写 tenant_id = xxx。
这里有必要多解释一下下面这条 SQL 中 sum 聚合函数里的 case when:
- 如果一个 sstable 比较小的话,多个 sstable 会共用一个 2 MB 宏块,计算存储空间的方式会比较特殊。when b.nested_offset = 0 就是用于判断 sstable 是否是小 sstable 的。
- 如果普通 sstable 的话(b.nested_offset = 0),就使用 2 MB * 宏块数量。
- 如果是小 sstable 的话(b.nested_offset != 0),就直接用这个 sstable 的 size。
sql
SELECT /*+ query_timeout(30000000) */
a.DATABASE_NAME,
sum(CASE WHEN b.nested_offset = 0
THEN IFNULL(b.data_block_count + b.index_block_count + b.linked_block_count, 0) * 2 * 1024 * 1024
ELSE IFNULL(b.size, 0) END) / 1024 / 1024 / 1024 AS data_size_in_GB
FROM oceanbase.CDB_OB_TABLE_LOCATIONS a
INNER JOIN oceanbase.__all_virtual_table_mgr b ON a.svr_ip = b.svr_ip
AND a.svr_port = b.svr_port
AND a.tenant_id = b.tenant_id
AND a.LS_ID = b.LS_ID
AND a.TABLET_ID = b.TABLET_ID
AND a.role = 'LEADER'
AND a.tenant_id = xxx
AND b.table_type >= 10
AND b.size > 0
GROUP BY a.DATABASE_NAME;
+---------------+-----------------+
| DATABASE_NAME | data_size_in_GB |
+---------------+-----------------+
| oceanbase | 0.003973903134 |
| test | 0.000002717599 |
| __recyclebin | 0.000006728805 |
| mysql | 0.000002369284 |
+---------------+-----------------+
4 rows in set (0.58 sec)
查询表的磁盘空间
以下 4.x 版本,需要使用 sys 租户,在 oceanbase 库中,查询指定 table 的磁盘占用。
- **4.2.1 BPX < 4.2.1 BP9 **
- 4.2.2
- 4.3.x < 4.3.2
需要在 SQL 中填写 tenant_id = xxx,如果不加 database_name = 'xxx' AND table_name = 'xxx' 查询出的结果包含。
sql
SELECT /*+ query_timeout(30000000) */
a.TENANT_ID,
a.DATABASE_NAME,
a.TABLE_NAME,
a.TABLE_ID,
sum(CASE WHEN b.nested_offset = 0
THEN IFNULL(b.data_block_count + b.index_block_count + b.linked_block_count, 0) * 2 * 1024 * 1024
ELSE IFNULL(b.size, 0) END) / 1024 / 1024 /1024 AS data_size_in_GB
FROM CDB_OB_TABLE_LOCATIONS a
INNER JOIN __all_virtual_table_mgr b
ON a.svr_ip = b.svr_ip
AND a.svr_port = b.svr_port
AND a.tenant_id = b.tenant_id
AND a.LS_ID = b.LS_ID
AND a.TABLET_ID = b.TABLET_ID
AND a.role = 'LEADER'
AND a.tenant_id = xxx
AND b.table_type >= 10
AND b.size > 0
-- WHERE database_name = 'xxx' AND table_name = 'xxx'
GROUP BY a.TABLE_ID;
+-----------+---------------+------------+----------+-----------------+
| TENANT_ID | DATABASE_NAME | TABLE_NAME | TABLE_ID | data_size_in_GB |
+-----------+---------------+------------+----------+-----------------+
| 1002 | test | t1 | 500024 | 0.000000458210 |
+-----------+---------------+------------+----------+-----------------+
1 row in set (0.66 sec)
以下版本,推荐使用下面这种更高性能查询方式。
- 4.2.1 BPX >= 4.2.1 BP9
- 4.2.x >= 4.2.3
- 4.3.x >= 4.3.2
这里也有必要多解释一下下面这条 SQL 中的 occupy_size 和 required_size。
- occupy_size:可以理解成 data_size,表示压缩后的数据量大小。比如 2 GB 数据压缩成了 1 MB,那么这个数据的 occupy_size 就是 1 MB。
- required_size:可以理解成 used_size,表示实际给数据分配的空间。比如 2G 数据压缩成了 1 MB,然后占用了一个宏块(一个宏块的默认大小 2 MB),那么这个数据的 required_size = 2 MB。
sql
-- 查普通用户表(非系统表)
SELECT atnt.tenant_id AS TENANT_ID,
avttl.table_id AS TABLE_ID,
atnt.tenant_name AS TENANT_NAME,
ad.database_name AS DATABASE_NAME,
avt.table_name AS TABLE_NAME,
sum(avtps.occupy_size) / 1024 / 1024 /1024 AS OCCUPY_SIZE_IN_GB,
sum(avtps.required_size) / 1024 / 1024 /1024 AS REQUIRED_SIZE_IN_GB
FROM oceanbase.__all_virtual_tablet_pointer_status avtps
INNER JOIN oceanbase.__all_virtual_tablet_to_ls avttl
ON avttl.tenant_id = avtps.tenant_id
AND avttl.tablet_id = avtps.tablet_id
INNER JOIN oceanbase.__all_tenant atnt
ON atnt.tenant_id = avttl.tenant_id
INNER JOIN oceanbase.__all_virtual_table avt
ON avt.tenant_id = avttl.tenant_id
AND avt.table_id = avttl.table_id
INNER JOIN oceanbase.__all_virtual_database ad
ON ad.tenant_id = atnt.tenant_id
AND ad.database_id = avt.database_id
INNER JOIN oceanbase.__all_virtual_ls_meta_table avlmt
ON avtps.tenant_id = avlmt.tenant_id
AND avtps.ls_id = avlmt.ls_id
AND avtps.svr_ip = avlmt.svr_ip
AND avtps.svr_port = avlmt.svr_port
AND avlmt.role = 1
WHERE atnt.tenant_id = 1002 AND database_name = 'test' AND table_name = 't2'
GROUP BY tenant_id,
table_id
ORDER BY tenant_id,
table_id
\G
*************************** 1. row ***************************
TENANT_ID: 1002
TABLE_ID: 500024
TENANT_NAME: mysql
DATABASE_NAME: test
TABLE_NAME: t1
OCCUPY_SIZE_IN_GB: 0.000000458210 -- 数据压缩后的真实大小
REQUIRED_SIZE_IN_GB: 0.000003814697 -- 4 MB,实际占用了两个宏块
1 row in set (0.32 sec)
What's more ?
从 4.3.4 版本开始,开始支持使用标准 CDB 视图查询空间占用。还是需要使用 sys 租户,在 oceanbase 库中查询。

sql
create table t1 (a int) ;
Query OK, 0 rows affected (0.278 sec)
select * from CDB_OB_TABLE_SPACE_USAGE\G
*************************** 1. row ***************************
TENANT_ID: 1002
TABLE_ID: 500024
TENANT_NAME: mysql
DATABASE_NAME: test
TABLE_NAME: t1
OCCUPY_SIZE: 492
REQUIRED_SIZE: 4096
1 row in set (0.52 sec)

sql
select * from CDB_OB_SERVER_SPACE_USAGE\G
*************************** 1. row ***************************
TENANT_ID: 1
TENANT_NAME: sys
SERVER_IP: 11.158.31.20
SERVER_PORT: 22602
SPACE_TYPE: Clog Data
DATA_BYTES: 1677562658
USAGE_BYTES: 1677562658
*************************** 2. row ***************************
TENANT_ID: 1
TENANT_NAME: sys
SERVER_IP: 11.158.31.20
SERVER_PORT: 22602
SPACE_TYPE: Index Data
DATA_BYTES: 1801
USAGE_BYTES: 16384
*************************** 3. row ***************************
TENANT_ID: 1
TENANT_NAME: sys
SERVER_IP: 11.158.31.20
SERVER_PORT: 22602
SPACE_TYPE: Meta Data
DATA_BYTES: 17129472
USAGE_BYTES: 17129472
*************************** 4. row ***************************
TENANT_ID: 1
TENANT_NAME: sys
SERVER_IP: 11.158.31.20
SERVER_PORT: 22602
SPACE_TYPE: Slog Data
DATA_BYTES: 16629760
USAGE_BYTES: 16629760
*************************** 5. row ***************************
TENANT_ID: 1
TENANT_NAME: sys
SERVER_IP: 11.158.31.20
SERVER_PORT: 22602
SPACE_TYPE: Table Data
DATA_BYTES: 2012
USAGE_BYTES: 16384
*************************** 6. row ***************************
TENANT_ID: 1
TENANT_NAME: sys
SERVER_IP: 11.158.31.20
SERVER_PORT: 22602
SPACE_TYPE: Tmp Data
DATA_BYTES: 0
USAGE_BYTES: 0

sql
obclient> select * from CDB_OB_SPACE_USAGE\G
*************************** 1. row ***************************
TENANT_ID: 1
TENANT_NAME: sys
ENDPOINT: NULL
PATH: NULL
SPACE_TYPE: Clog Data
USAGE_BYTES: 1677328015
*************************** 2. row ***************************
TENANT_ID: 1
TENANT_NAME: sys
ENDPOINT: NULL
PATH: NULL
SPACE_TYPE: Local Data
USAGE_BYTES: 67760128
附录
最后附上本文中出现的一些系统表的简单介绍:
- __all_virtual_table_mgr
- 用于通过 size 字段,查询所有 sstable、memtable 的 occupy_size。
- 表名中带 virtual 字样的都是虚拟表,查询时实时构建。查这张表是准的,但可能比较慢。
- __all_virtual_tablet_meta_table
- 查询到的 occupy_size,required_size 是基线 sstable 的大小。
- 只展示基线、多版本基线的大小(没有转储 sstable 的数据,和其他表的数据量对不上是符合预期的)。
- __all_virtual_tablet_pointer_status
- 查询所有 tablet 相关的信息
- occupy_size:tablet 的 occupy_size
- required_size:tablet 的 required_size
- 查询所有 tablet 相关的信息
- __all_space_usage
- 实体表,定时任务,定时更新。
- 展示每个 server 上的每个租户不同类型的空间占用信息。
- tenant file data : 租户下所有 tablet 的 occupy_size 总和。
💌
老纪的技术唠嗑局 不仅希望能持续给大家带来有价值的技术分享,也希望能和大家一起为开源社区贡献力量。如果你对 OceanBase 开源社区认可,点亮一颗小星星 ✨ 吧!你的每一个Star,都是我们努力的动力~💕
https://github.com/oceanbase/oceanbase