# ANALYZE \| ANALYSE
#### 功能描述
- 用于收集与数据库中普通表内容相关的统计信息，统计结果存储在系统表PG_STATISTIC、PG_STATISTIC_EXT下，执行ANALYZE命令后，可在上述系统表中查询收集到的统计信息，也可以通过系统视图PG_STATS、PG_EXT_STATS查询信息。执行计划生成器会使用这些统计数据，以确定最有效的执行计划。
- 如果没有指定参数，ANALYZE会分析当前数据库中的每个表和分区表。同时也可以通过指定table_name、column_name和partition_name参数把分析限定在特定的表、列或分区表中。
- ANALYZE\|ANALYSE VERIFY用于校验数据库目标表相关文件，具体支持校验类型见下表。
  
  | 页面类型\\校验类型        | 页面物理损坏 | 页面逻辑校验 | 元组校验        |
  |:---|:---|:---|:---|
  | UHEAP           | 支持     | 支持    | COMPLETE模式支持 |
  | HEAP            | 支持   | -     | COMPLETE模式支持 |
  | FSM             | 支持     | -     | -             |
  | VM               | -      | -    | -              |
  | UBTREE         | 支持      | 支持     | -              |
  | UBTREE.FSM(URQ) | 支持      | 支持    | -            |
  | BTREE           | 支持      | -   | -            |
  | BTREE.FSM      | 支持    | -     | -             |
     
  
- ANALYZE\|ANALYSE VERIFY执行完成所需时间与当前操作对象（数据库目标表或数据库）的大小以及当前机器的性能有关。
- 每次收集的统计信息，都会存入统计信息历史表（[GS_STATISTIC_HISTORY](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/gaussdb-08-0962.html)、[GS_STATISTIC_EXT_HISTORY](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/gaussdb-08-0961.html)、[GS_TABLESTATS_HISTORY](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/gaussdb-08-0964.html)）中，历史表存放的数量和统计信息的保留时间由GUC参数stats_history_record_limit和stats_history_retention_time控制。
 
#### 注意事项
- ANALYZE非临时表不支持在一个匿名块、事务块、函数或存储过程内被执行。ANALYZE临时表支持存储过程中被执行，不支持统计信息回滚操作。
- ANALYZE VERIFY如果不涉及远程读场景，远程读参数则不会生效。对于检测出关键系统表页面损坏的错误，将直接报错不再继续检测。
- 如果ANALYZE不指定参数，则默认处理当前用户拥有相应权限的表。如果参数指定了一个表参数，ANALYZE只处理指定的表。
- 要对一个表进行ANALYZE操作，用户必须是表的所有者或者被授予了指定表VACUUM权限，三权分立开关关闭时，默认系统管理员有该权限。数据库的所有者允许对数据库中除了共享目录以外的所有表进行ANALYZE操作（该限制意味着只有系统管理员才能真正对一个数据库进行ANALYZE操作）。ANALYZE会跳过那些用户没有权限的表。
- ANALYZE不收集无法做比较或等值运算的列，例如：CURSOR类型。
- 如果拟分析的表成了一个空表，ANALYZE不会记录该表的统计信息，而原来已有统计信息则会保留。
 
#### 语法格式
- 收集表的统计信息。
  ```
  { ANALYZE | ANALYSE } [ VERBOSE ]
      [ table_name [ ( column_name [, ...] ) ] ] [ WITH PARTITION_MODE ];
  ```
  ![](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/figure/zh-cn_image_0000002764309528.png "点击放大")
  

- 收集分区表的分区统计信息。
  ```
  { ANALYZE | ANALYSE } [ VERBOSE ]
      table_name [ ( column_name [, ...] ) ] PARTITION ( partition_name ) ;
  ```
  ![](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/figure/zh-cn_image_0000002764469464.png "点击放大")
  ![](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
  - 使用关键字PARTITION，partition_name必须为一级分区名字。
  
  - 分布式不支持二级分区。
    
- 收集外表的统计信息。
  ```
  { ANALYZE | ANALYSE } [ VERBOSE ]
      { foreign_table_name | FOREIGN TABLES };
  ```
  ![](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/figure/zh-cn_image_0000002793708069.png "点击放大")
  
 
- 收集全局二级索引的统计信息。
  ```
  { ANALYZE | ANALYSE } GLOBAL INDEX index_name FOR TABLE table_name;
  ```
  ![](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/figure/zh-cn_image_0000002793788267.png "点击放大")
  ![](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
  - 在对全局二级索引执行ANALYZE之前需要先对基表执行一次ANALYZE，以保证全局二级索引统计信息的准确性。
  
  - 在对全局二级索引进行REINDEX/REBUILD类型操作之后，需要先对基表进行一次ANALYZE，然后才能对全局二级索引进行ANALYZE，以保证全局二级索引统计信息的准确性。
  
  - 当前对全局二级索引进行统计信息收集必须指定index_name和table_name，且index_name必须是全局二级索引名。
  
  - 全局二级索引统计信息仅包括pg_class系统表中的统计信息（reltuple和relpages）。
  
  - 当ANALYZE执行时间窗内遇到并发的autoanalyze时，较低有可能会产生报错Duplicate key value violates unique constraint "gs_tablestats_history_relid_kind_time_index"，可以重新手动执行ANALYZE进行规避。
    
- 手动收集多列统计信息。
  ```
  { ANALYZE | ANALYSE } [ VERBOSE ]
      table_name (( column_1_name, column_2_name [, ...] )) [ WITH partition_mode ];
  ```
  ![](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/figure/zh-cn_image_0000002764309532.png "点击放大")
  ![](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
  - 如果关闭GUC参数enable_functional_dependency，每组多列统计信息最多支持32列。
  
  - 不支持收集多列统计信息的表：系统表。
    
- 自动收集多列统计信息。 打开auto_statistic_ext_columns参数后执行ANALYZE，自动根据该表的索引前缀创建多列统计信息，多列统计信息的列数不超过设置的auto_statistic_ext_columns值。
  例：表t存在索引(a,b,c,d)，设置auto_statistic_ext_columns参数为4，则analyze t将创建关于(a,b)、(a,b,c)、(a,b,c,d)的多列统计信息。
  ```
  { ANALYZE | ANALYSE } [ VERBOSE ] table_name [ WITH partition_mode ];
  ```
  ![](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/figure/zh-cn_image_0000002764309530.png)
  

- 检测当前库的数据文件。
  ```
  { ANALYZE | ANALYSE } VERIFY { FAST | COMPLETE };
  ```
  ![](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/figure/zh-cn_image_0000002793708073.png)
  ![](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
  - 由于该操作会直接从磁盘上读取数据，如果此时对正在校验的表有并发的DML操作，即并发修改磁盘文件，会导致获取的数据不准确，进而导致校验过程中出现误报的情况，因此建议在没有数据库业务时或者业务低峰期使用。
  
  - 为保障执行效率，建议执行此操作前，先执行checkpoint。
  
  - 支持对全库进行操作，由于涉及的表较多，建议以重定向保存结果**。**
    ```
    gsql -d database -p port -f sqlfile> sqllog.txt  2>&1
    ```
    
  
  - 只有对外可见的表对外提示NOTICE，内部表的检测会包含在它所依赖的外部表，不对外显示。
  
  - 对于全库操作，当出现损坏则直接报错，不再继续执行。
  
  - 只支持对当前库中的普通表、普通索引进行校验，不支持对本地临时表、UNLOGGED表进行校验，在实际过程中会自动跳过对不支持的表类型的校验。
  
  - 支持在备机执行。当库中表或数据较多时，执行时间较长，由于备机上有recovery业务，analyze verify业务可能被自动取消，并屏显相关报错信息。
    
- 检测表和索引的数据文件。
  ```
  { ANALYZE | ANALYSE } VERIFY { FAST  | COMPLETE } { table_name  [ CASCADE ] | index_name };
  ```
  ![](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/figure/zh-cn_image_0000002764469456.png "点击放大")
  ![](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
  - 支持对普通表的操作和索引表的操作，但不支持对索引表index使用CASCADE操作。原因是由于CASCADE模式用于处理主表的所有索引表，当单独对索引表进行检测时，无需使用CASCADE模式。
  
  - 对于主表的检测会同步检测主表的内部表，例如toast表等。
  
  - 当提示索引表损坏时，建议使用reindex命令进行重建索引操作。
  
  - 不支持对本地临时表、UNLOGGED表进行校验。
  
  - 支持在备机执行。
    
- 检测表分区的数据文件。
  ```
  { ANALYZE | ANALYSE } VERIFY { FAST | COMPLETE } table_name PARTITION (partition_name) [ CASCADE ];
  ```
  ![](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/figure/zh-cn_image_0000002793708071.png "点击放大")
  ![](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
  - 支持对表的单独分区进行检测操作，但不支持对索引表index使用CASCADE操作。
  
  - 不支持指定二级分区。
  
  - 支持在备机执行。
    
#### 参数说明
- **VERBOSE**
  启用显示进度信息。
  ![](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
  如果指定了VERBOSE，ANALYZE发出进度信息，表明目前正在处理的表。各种有关表的统计信息也会打印出来。
  
- **table_name**
  需要分析的特定表的表名（可能会带模式名），如果省略，将对数据库中的所有表（非外部表）进行分析。
  取值范围：已有的表名。
  
- **column_name** **，column_1_name，column_2_name**
  需要分析特定列的列名，默认为所有列。
  取值范围：已有的列名。
  
- **partition_name**
  如果table为分区表，在关键字PARTITION后面指定分区名partition_name表示分析该分区表的统计信息。
  取值范围：表的某一个分区名。
  
- **foreign_table_name**
  需要分析的特定表的表名（可能会带模式名）。
  取值范围：已有的表名。
  
- **FOREIGN TABLES**
  分析所有当前用户权限下的外表。
  
- **index_name**
  需要分析的特定索引表的表名（可能会带模式名）。
  取值范围：已有的表名。
  
- **FAST\|COMPLETE**
  对于行存表，FAST模式下主要对于行存表的CRC和page header进行校验，如果校验失败则会告警；而COMPLETE模式下，则主要对行存表的指针、tuple进行解析校验。
  
- **CASCADE**
  CASCADE模式下会对当前表的所有索引进行检测处理。
  
- **PARTITION_MODE**
  PARTITION_MODE适用于分区表级联收集统计信息，可选项和含义如[表1]所示。不适用于非分区表。
   表1PARTITION_MODE选项说明 
  | PARTITION_MODE选项      | 含义                                                                                                                                                                                                                                                                                                                    |
  |:---|:---|
  | ALL                  | 收集整表、一级分区的统计信息。                                                                                                                                                                                                                                                                                                         |
  | GLOBAL               | 收集整表的统计信息。                                                                                                                                                                                                                                                                                                             |
  | PARTITION             | 收集一级分区的统计信息。                                                                                                                                                                                                                                                                                                            |
  | GLOBAL AND PARTITION | 收集整表、一级分区的统计信息。                                                                                                                                                                                                                                                                                                       |
  | ALL COMPLETE          | 收集整表、一级分区的统计信息。                                                                                                                                                                                                                                                                                                        |
  | AUTO               | 缺省值，以statistic_granularity或default_statistic_granularity中配置的参数为准，其中表级参数statistic_granularity的优先级高于全局参数default_statistic_granularity。statistic_granularity介绍请参见[statistic_granularity](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/gaussdb-08-0271.html#ZH-CN_TOPIC_0000002764308858__li1188105517382)。 |
     
  ![](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
  - ALL和ALL COMPLETE的区别：ALL模式下对整表进行一次采样，ALL COMPLETE模式下对每个分区进行一次采样。对于分区来说，ALL COMPLETE模式比ALL模式计算统计信息更准确，同时也消耗更多资源。
  
  - 分区统计信息会在cplan裁剪到单分区时使用。建议结合统计信息的收集时间与业务实际需求，选择合适的分区表统计信息收集策略。
  
  - 在大规模导数后，建议使用ALL COMPLETE模式手动收集分区级的统计信息。
  
  - 从505.0.0之前版本升级到505.0.0及更高版本时，在升级观察期期间，PARTITION_MODE不生效，其行为与升级前版本保持一致。
  
  - 当对整个数据库进行ANALYZE操作时，不支持指定PARTITION_MODE，即不支持ANALYZE WITH GLOBAL等语法。
  
  - 当对整个数据库进行ANALYZE操作时，支持设置default_statistic_granularity为GLOBAL或ALL，此时ANALYZE行为和default_statistic_granularity的定义相同；当default_statistic_granularity设置为其他值时，ANALYZE行为退化为GLOBAL行为。
  
  - 不支持对二级分区的统计信息的收集。
  
  - ALL模式下，如果分区表上的partition_statistics_min_rows不为0，且GUC参数[enable_partition_statistics_min_rows](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/gaussdb-08-0783.html#ZH-CN_TOPIC_0000002764468986__section58205474258)打开时，会保证分区的最小采样行数为partition_statistics_min_rows，但是整表总采样行数上限会受到GUC参数[maintenance_work_mem](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/gaussdb-08-0761.html#ZH-CN_TOPIC_0000002793787487__zh-cn_topic_0059777577_s123a0cc8d6434028a6709bbfa876e8b0)控制。另外，在不同分区数据量存在严重倾斜的状态下，在ALL模式下执行ANALYZE后，建议补充一次针对整表的GLOBAL模式的ANALYZE，保证整表的统计信息可更准确的反映数据的倾斜特征。
    
 
#### 示例
- 收集表的统计信息。
  ```
  --创建customer_info表。
  gaussdb=# CREATE TABLE customer_info(
  wr_returned_date_sk INTEGER ,
  wr_returned_time_sk INTEGER ,
  wr_item_sk INTEGER NOT NULL
  ,wr_refunded_customer_sk INTEGER ) DISTRIBUTE BY HASH (wr_item_sk);
  --使用ANALYZE语句更新统计信息。
  gaussdb=# ANALYZE customer_info;
  --使用ANALYZE VERBOSE语句更新统计信息，并输出customer_info表的相关信息。
  gaussdb=# ANALYZE VERBOSE customer_info;
  INFO: analyzing "public.customer_info"(cn_5002 pid=53078)
  --使用ANALYZE VERBOSE输出customer_info表的wr_returned_time_sk列信息。
  gaussdb=# ANALYZE VERBOSE customer_info(wr_returned_time_sk);
  INFO:  analyzing "public.customer_info"(cn_5002 pid=53078)
  ```
  

- 收集分区表的统计信息。
  ```
  --创建分区表。
  gaussdb=# CREATE TABLE customer_par( 
  wr_returned_date_sk INTEGER ,
  wr_returned_time_sk INTEGER ,
  wr_item_sk INTEGER NOT NULL,
  wr_returned_customer_sk INTEGER)
  DISTRIBUTE BY HASH (wr_item_sk)PARTITION BY RANGE(wr_returned_date_sk)(PARTITION P1 VALUES LESS THAN(2452275),PARTITION P2 VALUES LESS THAN(2452640),PARTITION P3 VALUES LESS THAN(2453000),PARTITION P4 VALUES LESS THAN(MAXVALUE))ENABLE ROW MOVEMENT;
  --使用ANALYZE语句更新统计信息。
  gaussdb=# ANALYZE customer_par;
  --使用ANALYZE VERBOSE输出customer_par表的相关信息。
  gaussdb=# ANALYZE VERBOSE customer_par;
  INFO:  analyzing "public.customer_par"(cn_5001 pid=446617)
  --使用ANALYZE VERBOSE输出P1一级分区表的相关信息。
  gaussdb=# ANALYZE VERBOSE customer_par PARTITION(P1);
  INFO:  analyzing "public.customer_par"(cn_5001 pid=446617)
  ```
  

- 手动收集多列统计信息。
  ```
  --手动收集wr_returned_date_sk、wr_returned_time_sk这两列的统计信息。
  gaussdb=# ANALYZE VERBOSE customer_info (wr_returned_date_sk,wr_returned_time_sk);
  INFO:  analyzing "public.customer_par"(cn_5001 pid=446617)
  ```
  
- 自动收集多列统计信息。
  ```
  --给customer_info表创建索引。
  gaussdb=# CREATE INDEX customer_index ON customer_info USING btree(wr_returned_date_sk,wr_returned_time_sk,wr_item_sk,wr_refunded_customer_sk);
  --设置auto_statistic_ext_columns参数为4。
  gaussdb=# set auto_statistic_ext_columns=4;
  --自动收集多列统计信息。
  gaussdb=# ANALYZE VERBOSE customer_info;
  INFO:  analyzing "public.customer_info"(cn_5001 pid=446617)
  ```
  
- 检测当前库的数据文件。
  ```
  gaussdb=# ANALYZE VERIFY FAST;
  ```
  
- 检测表和索引的数据文件。
  ```
  --检查customer_info表。
  gaussdb=# ANALYZE VERIFY FAST customer_info;
  --检查customer_index索引。
  gaussdb=# ANALYZE VERIFY FAST customer_index;
  ```
  
- 检测表分区的数据文件。
  ```
  --检查customer_par分区表中的P1分区。
  gaussdb=# ANALYZE VERIFY FAST customer_par PARTITION (P1);
  ```
  
- 删除数据。
  ```
  --删除索引customer_index。
  gaussdb=# DROP INDEX customer_index;
  --删除表customer_info。
  gaussdb=# DROP TABLE customer_info;
  --删除分区表customer_par。
  gaussdb=# DROP TABLE customer_par;
  ```
  
 
