1. 为什么需要关注数据库存储空间
数据库存储空间管理是DBA日常工作中最基础也最重要的任务之一。想象一下,你的数据库就像一个仓库,表就是货架,数据就是货物。如果不定期盘点货架上的货物,仓库很快就会变得杂乱无章,找东西困难,甚至可能出现货物堆积到门口的情况。
在实际项目中,我遇到过好几次因为存储空间管理不善导致的问题。有一次,某个业务表突然暴涨到几十GB,直接占满了整个磁盘空间,导致数据库服务崩溃。还有一次,开发环境的一个测试表因为忘记清理,占用了上百GB空间,把整个服务器的性能都拖慢了。
KingbaseES作为一款企业级关系型数据库,提供了丰富的函数和视图来帮助我们监控存储空间使用情况。掌握这些工具,你可以:
- 及时发现异常增长的表
- 合理规划存储扩容
- 优化数据库性能
- 避免因空间不足导致的故障
2. 查询数据库大小
2.1 查询单个数据库大小
查询单个数据库大小是最基础的操作,KingbaseES提供了两个非常实用的函数:
-- 查询数据库大小(返回字节数) SELECT sys_database_size('kingbase'); -- 查询数据库大小(人类可读格式) SELECT sys_size_pretty(sys_database_size('kingbase'));第一个函数返回的是字节数,对于大多数人来说不太直观。第二个函数sys_size_pretty会自动将字节数转换为更友好的格式,比如MB、GB等。
我在实际使用中发现,sys_size_pretty函数非常智能,它会根据数据量大小自动选择合适的单位。比如:
- 小于1MB的数据会显示为KB
- 1MB到1GB之间的数据显示为MB
- 大于1GB的数据会显示为GB
2.2 查询所有数据库大小
作为DBA,我们经常需要了解整个实例中各个数据库的大小分布情况。这个查询可以帮助你快速找出占用空间最多的数据库:
SELECT sys_database.datname, sys_size_pretty(sys_database_size(sys_database.datname)) as size FROM sys_database ORDER BY sys_database_size(sys_database.datname) DESC;这个查询会返回所有数据库的名称和大小,并按大小降序排列。在实际运维中,我习惯定期运行这个查询,把结果记录下来,这样可以观察各个数据库的增长趋势。
3. 查询模式(SCHEMA)大小
3.1 查询单个模式大小
模式是KingbaseES中组织数据库对象的逻辑容器。要查询特定模式的大小,可以使用以下SQL:
SELECT sys_size_pretty(sum(table_size)::bigint) as "disk space", sum(table_size)::bigint as "total size" FROM ( SELECT sys_catalog.sys_namespace.nspname as schema_name, sys_total_relation_size(sys_catalog.sys_class.oid) as table_size FROM sys_catalog.sys_class JOIN sys_catalog.sys_namespace ON relnamespace = sys_catalog.sys_namespace.oid WHERE sys_catalog.sys_namespace.nspname = 'kingbase' ) t;这个查询稍微复杂一些,它通过连接系统表sys_class和sys_namespace来获取模式中所有表的总大小。sys_total_relation_size函数会返回表的大小,包括索引等附属对象。
3.2 查询所有模式大小
要查看数据库中所有模式的大小分布,可以使用以下查询:
SELECT schema_name, sys_size_pretty(sum(table_size)::bigint) as "disk space", sum(table_size)::bigint as "total size" FROM ( SELECT sys_catalog.sys_namespace.nspname as schema_name, sys_total_relation_size(sys_catalog.sys_class.oid) as table_size FROM sys_catalog.sys_class JOIN sys_catalog.sys_namespace ON relnamespace = sys_catalog.sys_namespace.oid WHERE sys_catalog.sys_namespace.nspname NOT IN ('information_schema','src_restrict','anon','dbms_sql','xlog_record_read','pg_catalog','pg_bitmapindex','sys_catalog','sysaudit','sysmac','sys') ) t GROUP BY schema_name;这个查询排除了系统模式,只显示用户创建的模式。在实际项目中,我发现这个查询特别有用,可以帮助快速定位哪些业务模块占用了最多的存储空间。
4. 查询表大小
4.1 查询单个表大小
表是最基本的存储单元,KingbaseES提供了多种函数来查询表的大小:
-- 查询表大小(人类可读格式) SELECT sys_size_pretty(sys_relation_size('kingbase.test_szie')); -- 查询表数据部分大小 SELECT sys_size_pretty(sys_table_size('kingbase.test_szie')); -- 查询表索引大小 SELECT sys_size_pretty(sys_indexes_size('kingbase.test_szie')); -- 查询表总大小(包括数据、索引等) SELECT sys_size_pretty(sys_total_relation_size('kingbase.test_szie'));这几个函数的区别在于:
sys_relation_size: 返回表的基本大小sys_table_size: 只计算表数据部分sys_indexes_size: 只计算索引部分sys_total_relation_size: 包含所有相关对象的总大小
在实际优化工作中,我经常使用这些函数来分析表的存储结构。比如,如果发现某个表的索引大小远远超过数据大小,可能就需要考虑索引是否合理了。
4.2 查询模式下所有表大小
要查看一个模式下所有表的大小情况,可以使用以下查询:
SELECT table_name, sys_size_pretty(table_size) AS table_size, sys_size_pretty(indexes_size) AS indexes_size, sys_size_pretty(total_size) AS total_size FROM ( SELECT table_name, sys_table_size(table_name) AS table_size, sys_indexes_size(table_name) AS indexes_size, sys_total_relation_size(table_name) AS total_size FROM ( SELECT ('"' || table_schema || '"."' || table_name || '"') AS table_name FROM information_schema.TABLES WHERE table_schema ='kingbase' ) AS all_tables ORDER BY total_size DESC ) AS pretty_sizes;这个查询会返回指定模式下所有表的详细信息,包括:
- 表名
- 数据部分大小
- 索引大小
- 总大小
结果按总大小降序排列,一眼就能看出哪些表是空间占用大户。我在性能优化时,通常会先运行这个查询,找出最大的几个表作为优化重点。
5. 实用技巧与常见问题
5.1 定期监控存储增长
建议设置定期任务,将上述查询结果保存下来。这样不仅可以监控存储使用情况,还能分析增长趋势。我通常会在每天业务低峰期运行这些查询,把结果存入专门的监控表。
5.2 处理大表的策略
当发现某个表异常增长时,可以考虑以下策略:
- 检查是否有可以归档的历史数据
- 考虑分区表策略
- 优化索引,删除不必要的索引
- 对大字段考虑使用TOAST存储
5.3 常见问题排查
在实际使用中,有几个常见问题需要注意:
- 查询结果异常大:可能是统计信息不准确,可以尝试运行
ANALYZE命令更新统计信息 - 查询速度慢:对大数据库的存储查询可能会消耗较多资源,建议在业务低峰期进行
- 权限问题:确保执行查询的用户有足够的权限访问系统表
5.4 自动化监控脚本
对于生产环境,我通常会编写自动化脚本,定期检查数据库大小,并在超过阈值时发送告警。这里分享一个简单的shell脚本示例:
#!/bin/bash DBNAME="your_database" WARNING_THRESHOLD=100 # GB SIZE_GB=$(psql -d $DBNAME -t -c "SELECT round(sys_database_size('$DBNAME')/1024/1024/1024)" | tr -d ' ') if [ $SIZE_GB -gt $WARNING_THRESHOLD ]; then echo "警告:数据库 $DBNAME 大小已超过阈值 ($SIZE_GB GB)" | mail -s "数据库空间告警" admin@example.com fi这个脚本会检查数据库大小,如果超过100GB就发送邮件告警。你可以根据需要调整阈值和告警方式。