更新统计信息
在数据库中,统计信息是规划器生成计划的源数据。没有收集统计信息或者统计信息陈旧会造成执行计划严重劣化,从而导致性能问题。
背景信息
ANALYZE语句可收集与数据库中表内容相关的统计信息,统计结果存储在系统表PG_STATISTIC中。查询优化器会使用这些统计数据,以生成最有效的执行计划。
建议在执行了大批量插入/删除操作后,例行对表或全库执行ANALYZE语句更新统计信息。目前默认收集统计信息的采样比例是30000行(即:guc参数default_statistics_target默认设置为100),如果表的总行数超过一定行数(大于1600000),建议设置guc参数default_statistics_target为-2,即按2%收集样本估算统计信息。
对于在批处理脚本或者存储过程中生成的中间表,也需要在完成数据生成之后显式的调用ANALYZE。
对于表中多个列有相关性且查询中有同时基于这些列的条件或分组操作的情况,可尝试收集多列统计信息,以便查询优化器可以更准确地估算行数,并生成更有效的执行计划。
生成统计信息
使用以下命令更新某个表或者整个database的统计信息。
1 2 |
ANALYZE tablename; --更新单个表的统计信息 ANALYZE; --更新全库的统计信息 |
使用以下命令进行多列统计信息相关操作。
1 2 3 4 5 6 |
ANALYZE tablename ((column_1, column_2)); --收集tablename表的column_1、column_2列的多列统计信息 ALTER TABLE tablename ADD STATISTICS ((column_1, column_2)); --添加tablename表的column_1、column_2列的多列统计信息声明 ANALYZE tablename; --收集单列统计信息,并收集已声明的多列统计信息 ALTER TABLE tablename DELETE STATISTICS ((column_1, column_2)); --删除tablename表的column_1、column_2列的多列统计信息或其声明 |
- 在使用ALTER TABLE tablename ADD STATISTICS语句添加了多列统计信息声明后,系统并不会立刻收集多列统计信息,而是在下次对该表或全库进行ANALYZE时,进行多列统计信息的收集。如果想直接收集多列统计信息,请使用ANALYZE命令进行收集。
- 使用EXPLAIN查看各SQL的执行计划时,如果发现某个表SEQ SCAN的输出中rows=10,rows=10是系统给的默认值,有可能该表没有进行ANALYZE,需要对该表执行ANALYZE。
提升统计信息质量
ANALYZE是按照随机采样算法从表上采样,根据样本计算表数据特征。采样数可以通过配置参数default_statistics_target进行控制,default_statistics_target取值范围为-100~10000,默认值为100。
- 当default_statistics_target > 0时;采样的样本数为300*default_statistics_target,default_statistics_target取值越大,采样的样本也越大,样本占用的内存空间也越大,统计信息计算耗时也越长。
- 当default_statistics_target < 0时,采样的样本数为 (default_statistics_target)/100*表的总行数,default_statistics_target取值越小,采样的样本也越大。当default_statistics_target < 0时会把采样数据下盘,不存在样本占用的内存空间的问题,但是因为样本过大,计算耗时长的问题同样存在。
default_statistics_target < 0时,实际采样数是 (default_statistics_target)/100*表的总行,所以又称之为百分比采样。
自动收集统计信息
当配置参数autoanalyze打开时,查询语句走到优化器发现表不存在统计信息,会自动触发统计信息收集,以满足优化器的需求。
注:只有对统计信息敏感的复杂查询动作(多表关联等操作)的SQL语句执行时才会触发自动收集统计信息;简单查询(比如单点,单表聚合等) 不会触发自动收集统计信息。