已索引
背景:
行里新采购了一套脱敏系统,该套系统可以直接从生产环境备库读取数据,脱敏后装载到测试环境(其底层逻辑是创建表后执行 INSERT 语句导入)。
问题:
测试环境与生产环境同样大小的表空间,但是在恢复过程中报表空间不足,经检查,生产环境表空间使用率只有60%多,测试环境的确使用光了。
分析:
1、检查测试环境和生产环境,该表空间都只有一个用户使用,排除了测试环境表空间被其它用户使用的可能。
2、对测试环境的表按大小排序,找出一个大表A与生产进行对比,发现测试环境30多G,生产环境只用0.3G。
3、统计该表记录数,生产和测试环境表的记录数是一样的。
4、分析生产和测试环境的建表语句,语句是一样的,且注意到该表是分区表。
5、随便挑选一个分区,记录条数 49条, 测试环境 8M,生产环境 0.0625M。该表总的分区数量4268,所以测试环境就是30多个G。
6、根据测试环境每个分区都是 8M 进行问题搜索,发现是 _partition_large_extents 参数设置为 True 影响了每个分区初始分配8M。
官方描述:
Initial Extent Size of a Partition Changed to 8MB from 64KB After Upgrade to 11.2.0.2 or Later (Doc ID 1295484.1)
简单说明如下:
从 11.2.0.2 开始,引入了隐藏参数 _partition_large_extents 和 _index_partition_large_extents。
默认值为 True,每个分区初始大小为8M(如果开了延迟分配的话,在插入记录时才真正分配)。
值为False或普通表默认占据空间大小仅0.0625m(64k)
The default value is TRUE which means all partitioned objects in the database will be created with 8MB extents if created in an auto allocate locally managed tablespace.
引入该参数的目的是为了减少分区数量,降低管理开销,提高性能,但如果一个分区中存放的记录数很少,就会浪费很多空间。
所以,我们平时在规划分区表时,不要盲目的每天、每周或每月一个分区,除了考虑业务逻辑,还要考虑一个分区中存放的记录数。
另外要说明的,如果使用 exp/imp 来做备份恢复也会有一样的问题,用 expdp/impdp 则不会有相同的问题。