
# GS_INSTR_UNIQUE_SQL
#### Unique SQL定义
数据库将接收到的每个SQL的文本字符串，都进行解析并生成内部解析树，遍历解析树并忽略其中的常数值，以一定的算法计算出来一个整数值作为Unique SQL ID，用来唯一标识这一类SQL，Unique SQL ID相同的一类SQL就叫做Unique SQL。
 #### 示例
假如，用户先后输入SQL:
```
select * from t1 where id = 1;
select * from t1 where id = 2;
```
那么，这两条SQL的统计信息会汇聚到同一个Unique SQL上：
```
select * from t1 where id = ?;
```
#### GS_INSTR_UNIQUE_SQL视图
GS_INSTR_UNIQUE_SQL视图显示当前节点收集的Unique SQL的执行信息，主要包括以下内容：
- Unique SQL ID以及归一化后的SQL文本字符串，归一化后的SQL文本如[示例]中所示。通常对于DML语句，在计算Unique SQL ID的过程中会忽略常量值。但对于DDL、DCL以及设置参数等语句，常量值不可以忽略。
- 执行次数（成功执行的次数），响应时间（数据库内部的SQL执行时间，包括最大、最小和总时间）。
- Cache/IO信息，包含block的物理读、逻辑读次数，仅统计执行成功的SQL在各DN节点上的相关信息。该统计值与查询执行当时所处理的数据量、所使用的内存、是否多次执行、内存管理策略、是否有其他并发查询等因素相关，反映整个查询执行过程中的buffer块物理读和逻辑读次数，不同时间执行可能统计值不同。
- 行活动，包含SELECT语句的结果集返回行数、更新行、插入行、删除行、顺序扫描行、随机扫描行等信息。除结果集返回行数与该SELECT语句的结果集行数一致、且仅在CN上记录外，其他行活动信息均在DN上记录，且统计数值反应的是整个查询执行过程中的行活动，包括对相关系统表、元数据表、数据表等做必要的扫描和修改，与对应数据量以及相关参数设置相关，即统计数值将会大于等于对实际数据表的扫描和修改。
- 时间分布，包含：DB_TIME/CPU_TIME/EXECUTION_TIME/PARSE_TIME/PLAN_TIME/REWRITE_TIME/PL_EXECUTION_TIME/PL_COMPILATION_TIME/NET_SEND_TIME/DATA_IO_TIME，相关定义见[表1]。该信息在CN和DN节点均有统计，视图查询时将汇总展示。
- 软硬解析次数，包含软解析（缓存计划）、硬解析（生成计划）的次数，即如果本次执行的是之前缓存的计划，软解析次数+1，如果本次执行的计划是重新生成的，则硬解析次数+1。该次数在CN和DN节点上都会统计，视图查询时将汇总展示。
Unique SQL收集功能存在以下约束：
- 只有执行成功的SQL才会显示其详细的统计信息，否则可能只记录query、node、user等信息。
- 如果开启Unique SQL收集功能，CN节点将对所有接收到的查询进行统计收集，包括工具和用户的查询等。
- 若一条SQL语句内部包含执行多条SQL语句、类似存储过程执行等场景，仅会对最外层SQL生成一条Unique SQL，所有子SQL的统计信息都会汇总到该Unique SQL记录上。
- Unique SQL的响应时间统计中不完全包含NET_SEND_TIME阶段的时间，所以EXECUTION_TIME和elapse_time等时间之间不存在大小比较关系。
- 对于类似begin;...;commit;等形式的事务块，当前不支持统计子句的解析时间（parse_time）。
普通用户访问GS_INSTR_UNIQUE_SQL视图，只能看到该用户相关的Unique SQL信息，管理员用户可以看到当前节点所有的Unique SQL信息。CN和DN上均可查询GS_INSTR_UNIQUE_SQL视图，DN上显示的是本节点内的Unique SQL统计信息，CN上显示的是本节点Unique SQL完整统计信息，即该CN节点会收集其他CN和DN上对应该CN的Unique SQL的执行信息，进行汇总展示。通过查询GS_INSTR_UNIQUE_SQL视图，能够定位由于消耗不同资源导致的Top SQL，为集群性能调优和维护提供依据。
后台线程每隔1小时检查一次所有的Unique SQL，将last_time在instr_unique_sql_timeout小时之前的Unique SQL删除。
 表1GS_INSTR_UNIQUE_SQL字段 
| 名称                  | 类型                       | 描述                                                                  |
|:---|:---|:---|
| node_name           | name                     | 接收SQL的CN节点名称。                                                       |
| node_id             | integer                  | 节点ID，等同于pgxc_node表中node_id。                                         |
| user_name           | name                     | 用户名称。                                                               |
| user_id             | oid                      | 用户ID。                                                               |
| unique_sql_id       | bigint                   | 归一化的UNIQUE SQL ID。                                                  |
| query               | text                     | 归一化的SQL文本。                                                          |
| n_calls             | bigint                   | 成功执行次数。                                                             |
| min_elapse_time     | bigint                   | SQL在数据库内的最小运行时间（单位：微秒）。                                             |
| max_elapse_time     | bigint                   | SQL在数据库内的最大运行时间（单位：微秒）。                                             |
| total_elapse_time   | bigint                   | SQL在数据库内的总运行时间（单位：微秒）。                                              |
| n_returned_rows     | bigint                   | 行活动-SELECT语句返回的结果集行数。                                               |
| n_tuples_fetched    | bigint                   | 行活动-随机扫描行（列存表/外表不统计）。                                               |
| n_tuples_returned   | bigint                   | 行活动-顺序扫描行（列存表/外表不统计）。                                               |
| n_tuples_inserted   | bigint                   | 行活动-插入行数。                                                           |
| n_tuples_updated    | bigint                   | 行活动-更新行数。                                                           |
| n_tuples_deleted    | bigint                   | 行活动-删除行数。                                                           |
| n_blocks_fetched    | bigint                   | buffer的块访问次数，即物理读/IO。                                               |
| n_blocks_hit        | bigint                   | buffer的块命中次数，即逻辑读/Cache。                                            |
| n_soft_parse        | bigint                   | 软解析次数（缓存计划）。                                                        |
| n_hard_parse        | bigint                   | 硬解析次数（生成计划）。                                                        |
| db_time             | bigint                   | 有效的DB执行时间，包含等待时间、网络发送时间等，若查询执行涉及到多线程，DB_TIME是多个线程的DB_TIME之和（单位：微秒）。 |
| cpu_time            | bigint                   | CPU的执行时间，不包含sleep时间（单位：微秒）。                                         |
| execution_time      | bigint                   | 查询执行器内的SQL执行时间，DDL语句、以及某些不经过执行器执行的语句（例如Copy语句）不计数（单位：微秒）。           |
| parse_time          | bigint                   | SQL解析时间（单位：微秒）。                                                     |
| plan_time           | bigint                   | SQL生成计划时间（单位：微秒）。                                                   |
| rewrite_time        | bigint                   | SQL重写时间（单位：微秒）。                                                     |
| pl_execution_time   | bigint                   | plpgsql过程化语言函数上的执行时间（单位：微秒）。                                        |
| pl_compilation_time | bigint                   | plpgsql过程化语言函数上的编译时间（单位：微秒）。                                        |
| net_send_time       | bigint                   | 网络时间，包含CN向客户端发送数据、DN向CN发送数据等时间（单位：微秒）。                              |
| data_io_time        | bigint                   | IO时间，文件IO耗时（单位：微秒）。                                                 |
| first_time          | timestamp with time zone | 该SQL第一次执行的时间。                                                       |
| last_time           | timestamp with time zone | 该SQL上一次执行的时间。                                                       |
   
