作者:付义,新炬网络高级技术专家。
某运营商**系统由于开发商运维人员使用drop分区进行历史数据清理引起了一次性能问题,庆幸的是操作时间是在晚上7点多,影响范围不大,持续时间80分钟。
运维人员的操作过程:
通过查询dba_tab_partitions确定需要清理的分区。
使用alter table *** drop partition ***;命令进行历史数据清理。
操作完成后,最终用户反馈该表涉及的查询模块效率变慢。经我们检查发现global index失效,随后我们做了重建索引以及收集统计信息操作,业务恢复正常。
事后,我们对该运维人员的目的进行了了解,他需要做临时需求,发现表空间不足,清理一个月的分区后发现空间释放未达到预期效果,又清理了一个月的分区。
现在我们模拟下当天发生的问题。
页面一般通过id进行查询数据,SQL如下:
正确的执行计划:
在drop 分区前确认索引状态及大小:
drop p201506分区:
检查索引状态及大小:
执行计划已经变为全表扫描:
至此,当日故障的简单模拟完成。通过模拟发现对存在global index的表进行drop partition会引起global index失效,可能导致大量全表扫描发生,最终引起整改数据库的性能下降。同时,我们发现drop partition后索引的大小未发生变化。那我们在drop partition同时进行update global indexes,索引大小是否发生变化呢?我们继续进行模拟测试。
重新生成测试表及数据的过程省略。
drop partition p201507同时更新global indexes
删除分区后索引状态及大小:
truncate partition同时 update global indexes是否会发生变化呢?
初步判断update global indexes时候索引的大小并不会发生变化。让我们dump出索引块看下。
由此可以确定,在update global indexes的时候仅更新了索引条目的状态,索引条目的数据并未减少,自然索引所占的空间不会发生变化。
那么如何才能让将索引使用的空间真正降低呢?
结论:
对分区表进行drop partition 或truncate partition 时,若该表存在global index则需要同时进行update global indexes操作,否则会出现global index失效,从而可能触发大量全表扫描,引起数据库整体性能下降。
使用update global indexes仅能保证全局索引有效,被清理数据对应的索引条目的标志位被更改为“D”,索引大小不会发生变化。进行此操作会产生大量IO,对性能存在一定影响,操作需要安排在非业务高峰期。若需要索引所占空间降低,需要进行rebuild操作。
需要通过drop partition 或truncate partition方式进行数据清理的表上尽量创建local index,数据的唯一性通过应用程序保证,而不是通过主键保证。
上一篇:Java项目构建新型利器——Gradle 下一篇:Latch Free、Library cache伪游标(pseudo cursor)之间的那些事