Table of Contents
前言
在项目维护中,之前执行脚本的执行一直都是正常(15分钟左右),突然有一天开始,执行脚本的变成两到三个小时,而且发现临时表空间在不断扩大,中途增加了一个临时表空间,还会出现临时表空间不足情况。后来发现,原来有一个表的数据量的数据量是比较大,看到该表的统计信息收集得有问题,统计信息的记录数为0,与实际不符,通过重新收集统计信息后,该表的执行脚本速度恢复正常,执行脚本时选择了合适的执行计划。那么什么是统计信息呢?统计信息是Oracle数据库对表、索引、列等数据库对象的特征和数据分布进行的描述。通过统计信息,Oracle能够决定最合适的执行计划来优化SQL查询。Oracle使用统计信息来优化查询执行计划,确保查询性能的最佳化。没有统计信息,优化器将无法准确估算查询的成本,可能导致执行计划不理想,影响查询效率;执行时间过长,导致性能问题。
统计信息包括:
- 表的行数
- 列的唯一值数
- 数据分布情况(如直方图)
- 索引的大小和选择性
- 表的块数和空闲空间等
统计信息的类型
表统计信息
表统计信息主要包括以下内容:
- 行数(NUM_ROWS):表中行的数量,影响查询成本的计算。
- 块数(BLOCKS):数据块的数量,反映表占用的存储空间。
- 空闲空间(CHAIN_CNT):行链的数量,影响表的更新性能。
列统计信息
列统计信息帮助优化器估算查询时需要扫描的数据量,包括以下内容:
- 数据分布(如直方图):帮助估算列值的分布情况,影响查询条件的选择。
- 基数(NUM_DISTINCT):列中的唯一值数量,影响索引的选择性。
索引统计信息
索引统计信息包括:
- 索引的大小:影响Oracle选择是否使用该索引的决策。
- 索引的选择性:索引能有效筛选出多少行,选择性高的索引通常会被优化器优先考虑。
如何收集统计信息
Oracle 执行统计信息收集有以下两种方式:自动收集统计信息与手动收集统计信息。
自动收集统计信息
自动统计信息收集机制,它会定期扫描数据库中的表和索引,并收集相关的统计数据。
可以通过查询 dba_autotask_client 来查看自动统计信息收集的 job 是否开启:

auto optimizer stats collection 的状态为 enabled 说明启用了自动任务,Oracle 会定期收集统计信息。
手动收集统计信息
当数据表的数据量发生大量变化时,可以手动收集统计信息,更新表的统计信息。如果表的数据量特别大,可以使用并行参数进行收集表的统计信息,如下:
--查询用户下的一个表的统计信息情况
SELECT *
FROM sys.dba_tab_statistics
WHERE owner = 'ERP'
AND table_name = 'REVIE_BILL';


如果在重新收集统计信息时,出现对象的统计信息被锁,可以执行以下语句进行解锁统计信息,再重新执行收集统计信息:
--解锁
call dbms_stats.unlock_table_stats(ownname => 'ERP',tabname => 'REVIE_BILL');
--收集统计信息
call dbms_stats.gather_table_stats(ownname => 'ERP',tabname => 'REVIE_BILL');
除针对表进行收集统计信息,还可以进行用户级或某些索引等(dbms_stats.gather_schema_stats、dbms_stats.gather_index_stats)。如果需要将统计信息迁移到其他数据库,可以导出和导入统计信息(dbms_stats.export_schema_stats、dbms_stats.import_schema_stats)。
总结
在日常维护中,收集统计会经常使用,可以通过正确的收集、查看、管理和优化统计信息来提高查询性能,也可参考以下几点来进行优化:
- 定期更新统计信息:确保优化器正确估算执行计划的基础。
- 结合业务需求收集统计信息:对于数据变化较小的表,收集频率可以适当降低。
- 使用并行收集:如果表非常大,并行收集统计信息可以提高收集速度。
- 自动收集与手动收集结合:自动统计信息收集适合一般场景,但对于一些特殊的复杂查询或表,可能需要手动收集更细致的统计信息。




