# ANALYZE \| ANALYSE
#### 功能描述
用于收集有关数据库中表内容的统计信息，统计信息分为表级和列级。其中，表级统计信息存储在PG_CLASS中，列级统计结果存储在系统表PG_STATISTIC下。执行计划生成器会使用这些统计数据，以确定最有效的执行计划。
它的主要作用是：
- **优化查询性能**：为查询优化器提供数据分布信息，帮助生成更高效的执行计划。
- **提高查询计划准确性**：使优化器能更准确地估算不同查询路径的成本。
- **支持索引选择**：帮助优化器决定是否使用索引以及使用哪个索引。
 
#### 需要执行ANALYZE的场景
- **大规模数据变化** ：
  大规模数据导入/UPDATE/DELETE等操作，会导致表数据行数变化，新增的大量数据也会导致数据特征发生大的变化，此时需要对表重新收集统计信息。
  
- **查询新增数据** ：
  常见于业务表新增数据查询场景，这个也是客户现场中最常出现的统计信息没有及时更新而导致的数据查询不准确的问题，这种场景最主要的特征如下：
  - 存在一个按照时间增长的业务表。
  
  - 业务表每天入库新一天的数据。
  
  - 数据入库之后查询新增数据进行数据加工分析。
  
  
  在最后步骤的数据加工分析时，最常用的方法就是使用Filter条件从分区表中筛选数据，如
  ```
  passtime > '2020-01-19 00:00:00' AND passtime < '2020-01-20 00:00:00'
  ```
  假如新增数据入库之后没有执行ANALYZE，优化器发现Filter条件中的passtime取值范围超过了统计信息中记录的passtime值的上边界，会把估算满足passtime \> '2020-01-19 00:00:00' AND passtime \< '2020-01-20 00:00:00' 的tuple个数为1条，导致估算行数验证失真。
  
 
#### 关于自动收集统计信息（autoanalyze）
后台已默认开启了GUC参数autovacuum用于控制自动执行analyze，系统会根据表修改量进行动态采样、轮询采样。详情参见[analyze最佳实践](https://bbs.huaweicloud.com/blogs/418058)。
#### 注意事项
- 如果没有指定参数，ANALYZE会分析当前数据库中的每个表和分区表。同时也可以通过指定table_name、column和partition_name参数把分析限定在特定的表、列或分区表中。
- 能够执行ANALYZE特定表的用户，包括表的所有者、表所在数据库的所有者、通过GRANT被授予该表上ANALYZE权限的用户或者被授予了gs_role_analyze_any角色的用户以及有SYSADMIN属性的用户。
- 在百分比采样收集统计信息时，用户需要被授予ANALYZE和SELECT权限。
- 开启分区统计信息参数enable_analyze_partition，对分区表设置表级incremental_analyze参数，会先对无统计信息或有数据变化的分区执行ANALYZE，然后通过合并分区统计信息方式生成分区主表的统计信息。
- 开启analyze_options参数（9.1.1.100及以上集群版本支持）中的analyze_on_vw选项，支持对列存3.0表在弹性VW上执行ANALYZE，在弹性VW的数据节点上完成数据采样，在CN上使用采样数据进行统计信息的计算。

- 仅8.1.1及以上集群版本支持在匿名块、事务块、函数或存储过程内对单表进行ANALYZE操作。
- 对于ANALYZE全库，库中各表的ANALYZE处于不同的事务中，所以不支持在匿名块、事务块、函数或存储过程内对全库执行ANALYZE。
- 统计信息的回滚操作不支持PG_CLASS中相关字段的回滚。
- 全局临时表在每个会话的ANALYZE的统计信息独立。每个会话都有自己的统计信息。
- ANALYZE\|ANALYSE VERIFY用于检测数据库中普通表（行存表、列存表）的数据文件是否损坏，目前此命令暂不支持HDFS表。
- ANALYZE VERIFY操作处理的大多为异常场景检测需要使用RELEASE版本。ANALYZE VERIFY场景不触发远程读，因此远程读参数不生效。对于关键系统表出现错误被系统检测出页面损坏时，将直接报错不再继续检测。
![](https://support.huaweicloud.com/sqlreference-911-dws/public_sys-resources/warning_3.0-zh-cn.png)
- 单次新增、修改量占表总量10%以上场景，需在业务中增加显式Analyze操作。
- 更多开发设计规范参见[总体开发设计规范](https://support.huaweicloud.com/devg-dws/dws_04_0075.html)。
 
#### 语法格式
- 收集表的统计信息。
  ```
  { ANALYZE | ANALYSE } [ { VERBOSE | LIGHT | FORCE | PREDICATE } ]
      [ table_name [ ( column_name [, ...] ) ] ];
  ```
  

- 收集分区的统计信息。
  ```
  { ANALYZE | ANALYSE } [ { VERBOSE | LIGHT | FORCE } ]
      [ table_name [ ( column_name [, ...] ) ] ]
      PARTITION ( partition_name ) ;
  ```
  ![](https://support.huaweicloud.com/sqlreference-911-dws/public_sys-resources/caution_3.0-zh-cn.png)
  - 8.2.1.200及以上集群版本支持通过设置GUC参数enable_analyze_partition（默认值为off）控制是否允许对表的指定分区收集统计信息。**该参数开启后，分区表的统计信息获取方式将发生变化。如需开启请联系技术支持**。
  
  - 8.2.1.200以下的集群版本，普通分区表语法上支持对表的指定分区收集统计信息，但功能上暂未实现。对指定分区执行ANALYZE，会返回WARNING提示。
  
  
  
  - 不支持使用临时采样表来收集分区的统计信息。
  
  - 不支持分区上的多列统计信息和表达式统计信息。
    
- 收集外表的统计信息。
  ```
  { ANALYZE | ANALYSE } [ VERBOSE ]
      { foreign_table_name | FOREIGN TABLES };
  ```
  
 
- 收集多列统计信息
  ```
  {ANALYZE | ANALYSE} [ VERBOSE ]
      table_name (( column_1_name, column_2_name [, ...] ));
  ```
  ![](https://support.huaweicloud.com/sqlreference-911-dws/public_sys-resources/note_3.0-zh-cn.png)
  - 收集多列统计信息时，请设置GUC参数default_statistics_target为负数，以使用百分比采样方式。
  
  - 每组多列统计信息最多支持32列。
  
  - 不支持收集多列统计信息的表：系统表、HDFS外表复制表、全局临时表。
    
- 检测当前库的数据文件
  ```
  {ANALYZE | ANALYSE} VERIFY {FAST|COMPLETE|DISTRIBUTION};
  ```
  ![](https://support.huaweicloud.com/sqlreference-911-dws/public_sys-resources/note_3.0-zh-cn.png)
  - 支持对全库进行操作，由于涉及的表较多，建议以重定向保存结果**gsql -d database -p port -f "verify.sql"\> verify_warning.txt 2\>\&1**。
  
  - 不支持HDFS表（内表和外表），不支持临时表和UNLOGGED表。
  
  - 只有外部表提示NOTICE，内部表的检测会包含在它所依赖的外部表，不对外显示。
  
  - 该语句支持容错处理。
  
  - 对于全库操作时，当关键系统表出现损坏则直接报错，不再继续执行。
  
  - DISTRIBUTION选项仅9.1.1.200及以上集群版本支持。
    
- 检测表和索引的数据文件
  ```
  {ANALYZE | ANALYSE} VERIFY {FAST|COMPLETE|DISTRIBUTION} table_name|index_name [CASCADE];
  ```
  ![](https://support.huaweicloud.com/sqlreference-911-dws/public_sys-resources/note_3.0-zh-cn.png)
  - 支持对普通表的操作和索引表的操作，但不支持对索引表index使用CASCADE操作。原因是CASCADE模式用于处理主表的所有索引表，当单独对索引表进行检测时，无需使用CASCADE模式。
  
  - 不支持HDFS表（内表和外表），不支持临时表和UNLOGGED表。
  
  - 对于主表的检测会同步检测主表的内部表，例如toast表、cudesc表等。
  
  - 当提示索引表损坏时，建议使用reindex命令进行重建索引操作。
  
  - DISTRIBUTION选项仅9.1.1.200及以上集群版本支持，DISTRIBUTION不支持CASCADE模式。
    
- 检测表分区的数据文件
```
{ANALYZE | ANALYSE} VERIFY {FAST|COMPLETE|DISTRIBUTION} table_name PARTITION {(partition_name)}[CASCADE];
```
![](https://support.huaweicloud.com/sqlreference-911-dws/public_sys-resources/note_3.0-zh-cn.png)
- 支持对表的单独分区进行检测操作，但不支持对索引表index使用CASCADE操作。
- 不支持HDFS表（内表和外表），不支持临时表和UNLOGGED表。
- DISTRIBUTION选项仅9.1.1.200及以上集群版本支持，DISTRIBUTION不支持CASCADE模式。
 
#### 参数说明
表1ANALYZE \| ANALYSE参数说明 
| 参数                            | 描述                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         | 取值范围                                                   |
|:---|:---|:---|
| VERBOSE                     | 启用VERBOSE后，ANALYZE会发出进度信息，表明目前正在处理的表。各种有关表的统计信息也会打印出来。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    | -                                                         |
| LIGHT                       | 轻量化模式下对表收集的统计信息保存到内存中，不写入系统表，执行时对表加一级锁，该选项请加括号使用，例如ANALYZE (LIGHT) t1。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   | -                                                        |
| FORCE                        | FORCE模式支持表的统计信息被锁定的情况下进行强制执行ANALYZE，该选项请加括号使用，例如ANALYZE (FORCE) t1。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        | -                                                      |
| PREDICATE                    | PREDICATE模式表示只计算当前识别到的[谓词列](https://support.huaweicloud.com/devg-911-dws/dws_04_0946.html)的统计信息，该参数仅9.1.0.100及以上集群版本支持。是否支持谓词列的ANALYZE操作由GUC参数[analyze_predicate_column_threshold](https://support.huaweicloud.com/devg-911-dws/dws_04_0912.html)控制，取值为0表示关闭，大于0表示开启谓词列收集功能，且仅对列数大于等于此取值的表进行谓词列ANALYZE。 该选项请加括号使用，例如ANALYZE (PREDICATE) xxx。 谓词信息是在查询解析阶段收集，动态采样也支持谓词列采样。                                                                                                                                                                                                                                                                                                                                                                                                    | -                                                    |
| table_name                  | 需要分析的特定表的表名（可能会带模式名），如果省略，将对数据库中的所有表（非外部表）进行分析。 对于ANALYZE收集统计信息，目前仅支持行存表、列存表、HDFS表、ORC格式的OBS外表、CARBONDATA格式的OBS外表、协同分析的外表。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   | 表名长度不超过63个字符，以字母或下划线开头，可包含字母、数字、下划线、$、#。                |
| column_name                 | 需要分析特定列的列名，默认为所有列。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      | 已有的列名，格式为：column_1_name，column_2_name，column_3_name.... |
| partition_name                | 表示分析该分区表的统计信息。目前语法上支持分区表执行ANALYZE，但功能实现上暂不支持对指定分区统计信息的分析。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | 已有的分区表名。                                               |
| foreign_table_name            | 需要分析的特定外表的表名（可能会带模式名），该表的数据存放于HDFS分布式文件系统中。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              | 已有的外表名。                                               |
| FOREIGN TABLES                | 分析所有当前用户权限下，数据位于HDFS分布式文件系统中的HDFS外表。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      | 已有的HDFS外表。                                              |
| index_name                   | 需要分析的特定索引表的表名（可能会带模式名）。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    | 已有的索引名。                             |
| FAST\|COMPLETE\|DISTRIBUTION | 不同模式下，对行存表、列存表、哈希分布表的数据分布进行校验。 行存表： - FAST模式下，主要对于行存表的CRC和page header进行校验，如果校验失败则会告警。  - COMPLETE模式下，主要对行存表的指针、tuple进行解析校验。   列存表： - FAST模式下，主要对于列存表的CRC和magic进行校验，如果校验失败则会告警。  - COMPLETE模式下，主要对列存表的CU进行解析校验。   哈希分布表： DISTRIBUTION模式下，主要对于哈希分布表在DN上的数据分布正确性进行校验，如果校验失败则会告警。 | -                                                      |
| CASCADE                      | CASCADE模式下会对当前表的所有索引进行检测处理。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                | -                                                       |
   
#### 示例
- 使用ANALYZE语句更新表customer_info统计信息。
  ```
  DROP TABLE IF EXISTS customer_info;
  CREATE TABLE customer_info (name varchar(50), email varchar(100));
  ANALYZE customer_info;
  ```
  
- 使用ANALYZE VERBOSE语句更新表customer_info统计信息，并输出表的相关信息。
  ```
  ANALYZE VERBOSE customer_info;
  ```
  ![](https://support.huaweicloud.com/sqlreference-911-dws/figure/zh-cn_image_0000002568839471.png "点击放大")
  
- 更新表customer_info中特定列name，email的统计信息。
  ```
  ANALYZE customer_info (name, email);
  ```
  
- 使用轻量化模式更新表customer_info的统计信息。
  ```
  ANALYZE (LIGHT) customer_info;
  ```
  
- 使用强制模式更新表customer_info的统计信息，即使表已被锁定。
  ```
  ANALYZE (FORCE) customer_info;
  ```
  
- 只更新谓词列的统计信息，只会对当前为止收集到的谓词列进行采样，最后在查询业务稳定后使用。
  ```
  ANALYZE (PREDICATE) customer_info;
  ```
  通过函数**pg_stat_get_predicate_columns**可以查询当前已收集了表的哪些谓词列，注意以下示例的表名为"customer_info"，实际执行时请替换表名。
  ```
  SELECT pr.attnum,pa.attname FROM pg_catalog.pg_stat_get_predicate_columns('customer_info'::regclass) pr LEFT JOIN pg_attribute pa ON pa.attrelid='customer_info'::regclass AND pa.attnum = pr.attnum;
  ```
  
 
