进来做性能调优,测试两个表(一个百万级、一个千万级)的批量插入速度,免不了要删掉所有记录后重来。众所周知,TRUNCATE TABLE要比DELETE FROM迅速很多,所以一直是用TRUNCATE TABLE。
但折腾过几回后,发现有关这两个表的SELECT、DELETE、UPDATE语句变得巨慢。查看这些SQL的执行计划,也都跟预想一样利用了索引。但无论如何调整,就一直很慢。
后来某天突来灵感,会不会是索引本身有了问题?于是rebuild了索引,为保险起见再重做表分析,结果立即见效,所有sql恢复了以前的运行速度。
个人猜测,因为TRUNCATE TABLE是直接释放数据页,很有可能会引起索引数据的不一致或紊乱;表越大、TRUNCATE次数越多,影响程度越严重。
再进一步测试,得到如下的经验:
- 在本人的测试环境(Oracle 12c, 64G PGA)中,经过三四次TRUNCATE就须重建索引;
- 重建索引的合适时机是批量插入完成后,而刚TRUNCATE完成就重建索引,貌似毫无效果;
- 重做表分析也能带来一些性能提升,但不如重建索引直接见效。