ADBPG的统计信息记录了描述数据库数据的相关元数据,例如表的总行数、max/min值、null个数等。统计信息的作用非常关键:查询优化器需要根据最新的统计信息,生成出执行最优的计划。如果统计信息不准或者没有统计信息,优化器有可能会生成执行效率很差的执行计划,例如,对于一个具有索引且行数很多的数据表来说,以索引列为where条件对数据表进行点查,如果统计信息失效,那么优化器可能不会使用索引对数据表进行查询,而是使用遍历的方式对数据表进行查询,这种情况下后者的性能会比前者慢几个数量级。因此,在正确的时机进行统计信息的收集,是查询性能不会劣化的重要保证之一。

统计信息收集方式

ADBPG数据库内核参数gp_autostats_mode的值决定了数据库应该以什么方式去收集统计信息:

  • none:禁止自动收集统计信息,所有统计信息的收集需要手动执行命令去收集。
  • on_no_stats:当CREATE TABLE AS SELECT、INSERT或者COPY命令在没有统计信息的表上执行时,会触发对这个表做一次统计信息收集。但是除此之外,还是需要手动执行命令去收集统计信息。
  • on_change:当CREATE TABLE AS SELECT、INSERT、UPDATE、DELETE或者COPY命令在表上执行时,如果影响的行数超过了gp_autostats_on_change_threshold内核参数所设置的阈值时,会触发对这个表做一次统计信息收集。该模式完全自动化,不再需要额外地去手动执行统计信息收集命令。

手动收集统计信息命令

如果gp_autostats_mode配置的不是on_change而需要进行手动收集统计信息的时候,有如下三种方式:

  • 不带任何参数运行ANALYZE命令会为数据库中所有的表收集统计信息,该统计信息收集方式运行时间可能会比较长。
  • 可以只对某个表收集统计信息,此时运行ANALYZE命令需要带上表名作为参数,例如:ANALYZE t1;
  • 可以只对某个表的若干个列收集统计信息,此时运行ANALYZE需要带上表名和列名作为参数,例如:ANALYZE t1(a, b);

手动收集统计信息时机

手动收集统计信息时,并不需要收集的非常频繁。可以在满足以下条件的时候,再去手动执行ANALYZE命令收集统计信息:

  • 导入数据后、超过20%数据更新(IUD)后、创建索引后,需进行统计信息收集。
  • ETL任务过程中,会涉及多次IUD,可根据业务情况,在其中适当添加ANALYZE语句。
  • 调优过程中,从执行计划中看到表行数估算为1行,计划中出现较多的Broadcast、Sort+GroupByAgg、NestLoop等算子时,考虑对相应数据表进行 ANALYZE。