签到成功

知道了

CNDBA社区CNDBA社区

OceanBase 统计信息 管理 说明

2023-07-13 08:27 1546 0 原创 OceanBase
作者: dave

1 统计信息概述

统计信息是指优化器统计信息(Optimizer Statistics),描述数据库中表和列信息的数据集合。

优化器代价模型(Optimizer Cost Model)依赖于查询中涉及到的表、列、谓词等对象的统计信息来选取计划,优化器可以利用统计信息来优化计划的选择,所以统计信息是代价模型中选取最优执行计划的关键。

http://www.cndba.cn/dave/article/131416

在 OceanBase 数据库优化器中,统计信息以普通数据的形式存储在内部表中,并且会在本地维护统计信息的缓存,以提高优化器对统计信息的访问速度。

统计信息包含表统计信息(Table Level Statistics)和列统计信息(Column Level Statistics)两种类型。

表的统计信息主要包含以下信息:

1.表的基本信息(包括 tenant_id、table_id、partition_id 等)
2.表的统计信息类型(信息级别分为 GLOBAL、PARTITION 和 SUBPARTITION)
3.表的行数
4.表所占用的宏块数
5.表所占用的微块数
6.表的平均行长
7.表的收集统计信息时间
8.表的统计信息是否锁定

列的统计信息主要包含以下信息:

1.列的基本信息(包括 tenant_id、table_id、partition_id、column_id)
2.列的统计信息类型(信息级别分为 GLOBAL、PARTITION 和 SUBPARTITION)
3.列中不同的值的数量 NDV(Number of Distinct Values)
4.列中 NULL 值的数量
5.列的最大值和最小值
6.列的采样数据量大小
7.列的直方图的稠密度
8.列的直方图桶个数
9.直方图类型(频率直方图/ TopK 直方图/混合直方图)

OceanBase 数据库 MySQL 模式下用于查询相关统计信息的视图如下:

1.OCEANBASE.DBA_TAB_STATISTICS:用于查询表级的统计信息。
2.OCEANBASE.DBA_TAB_COL_STATISTICS:用于查询 GLOBAL 级别的列级统计信息。
3.OCEANBASE.DBA_PART_COL_STATISTICS:用于查询 PARTITON 级别的列级统计信息。
4.OCEANBASE.DBA_SUBPART_COL_STATISTICS:用于查询 SUBPARTITON 级别的列级统计信息。
5.OCEANBASE.DBA_TAB_HISTOGRAMS:用于查询 GLOBAL 级别的列级直方图统计信息。
6.OCEANBASE.DBA_PART_HISTOGRAMS:用于查询 PARTITON 级别的列级直方图统计信息。
7.OCEANBASE.DBA_SUBPART_HISTOGRAMS:用于查询 SUBPARTITON 级别的列级直方图统计信息。
8.OCEANBASE.DBA_IND_STATISTICS:用于查询索引统计信息。

查看表的统计信息:

obclient [oceanbase]> select owner,TABLE_NAME ,partition_name,NUM_ROWS ,AVG_ROW_LEN ,LAST_ANALYZED  from OCEANBASE.DBA_TAB_STATISTICS where owner='cndba';
+-----------+--------------------------------+----------------+----------+-------------+----------------------------+
| owner     | TABLE_NAME                     | partition_name | NUM_ROWS | AVG_ROW_LEN | LAST_ANALYZED              |
+-----------+--------------------------------+----------------+----------+-------------+----------------------------+
| cndba | chat_req_records_transit       | NULL           |        0 |           0 | 2023-07-10 17:07:38.295836 |
| cndba | chat_record_tree               | NULL           |       29 |         156 | 2023-07-10 17:07:38.389382 |
| cndba | chat_score                     | NULL           |   119013 |         100 | 2023-07-10 17:07:38.569771 |
| cndba | freeze_user_record             | NULL           |   457272 |          80 | 2023-07-10 17:07:38.983850 |
| cndba | chat_violation                 | NULL           |     1698 |         100 | 2023-07-10 17:07:39.032010 |
| cndba | test_data_industry_copy1       | NULL           |        0 |           0 | 2023-07-10 17:07:39.067542 |
| cndba | chat_complaint                 | NULL           |        0 |           0 | 2023-07-10 17:07:39.104315 |
| cndba | chat_resp_records_transit      | NULL           |        0 |           0 | 2023-07-10 17:07:39.137004 |
| cndba | ow_survey                      | NULL           |    10648 |         100 | 2023-07-10 17:07:39.212023 |
| cndba | chat_special_uid               | NULL           |      392 |         133 | 2023-07-10 17:07:39.244743 |
| cndba | ow_register                    | NULL           |        1 |         298 | 2023-07-10 17:07:39.307249 |
| cndba | sparkdesk_industry             | NULL           |       11 |          77 | 2023-07-10 17:07:39.344826 |
| cndba | chat_bot_market                | NULL           |     2078 |         714 | 2023-07-10 17:07:39.427636 |
| cndba | bot_type_list                  | NULL           |       18 |         151 | 2023-07-10 17:07:39.513939 |
| cndba | call_out_record                | NULL           |   449476 |         351 | 2023-07-10 17:07:40.788247 |
| cndba | chat_properties                | NULL           |        2 |         129 | 2023-07-10 17:07:40.850132 |
| cndba | screen                         | NULL           |        0 |           0 | 2023-07-10 17:07:40.899464 |
| cndba | test_data_industry             | NULL           |       11 |          77 | 2023-07-10 17:07:40.932092 |
| cndba | chat_token_records             | NULL           | 37031506 |         183 | 2023-07-10 17:07:42.644534 |
| cndba | manage_user                    | NULL           |        0 |           0 | 2023-07-10 17:07:42.690298 |
| cndba | chat_bot_list                  | NULL           |   420923 |         498 | 2023-07-10 17:07:43.185654 |
| cndba | chat_vip_users                 | NULL           |    33118 |         212 | 2023-07-10 17:07:43.352218 |
| cndba | chat_appointment_log           | NULL           |     4126 |         110 | 2023-07-10 17:07:43.408195 |
| cndba | prompt_type                    | NULL           |        6 |          61 | 2023-07-10 17:07:43.443032 |
| cndba | test_data_pv_uv                | NULL           |        7 |          76 | 2023-07-10 17:07:43.470428 |
| cndba | chat_bot_remove                | NULL           |      151 |         615 | 2023-07-10 17:07:43.511825 |
| cndba | chat_resp_records              | NULL           | 17942553 |         957 | 2023-07-10 17:08:37.146617 |
| cndba | chat_resp_records              | p20230410      |        0 |           0 | 2023-07-10 17:08:37.146617 |
| cndba | chat_resp_records              | p20230417      |        0 |           0 | 2023-07-10 17:08:37.146617 |
| cndba | chat_resp_records              | p20230424      |        0 |           0 | 2023-07-10 17:08:37.146617 |
| cndba | chat_resp_records              | p20230501      |        0 |           0 | 2023-07-10 17:08:37.146617 |
| cndba | chat_resp_records              | p20230508      |        0 |           0 | 2023-07-10 17:08:37.146617 |
| cndba | chat_resp_records              | p20230515      |        0 |           0 | 2023-07-10 17:08:37.146617 |
| cndba | chat_resp_records              | p20230522      |        0 |           0 | 2023-07-10 17:08:37.146617 |
| cndba | chat_resp_records              | p20230529      |        0 |           0 | 2023-07-10 17:08:37.146617 |
| cndba | chat_resp_records              | p20230605      |        0 |           0 | 2023-07-10 17:08:37.146617 |
| cndba | chat_resp_records              | p20230612      |  3980882 |         991 | 2023-07-10 17:08:37.146617 |
| cndba | chat_resp_records              | p20230619      |  4479632 |         940 | 2023-07-10 17:08:37.146617 |
| cndba | chat_resp_records              | p20230626      |  3134480 |         943 | 2023-07-10 17:08:37.146617 |
| cndba | chat_resp_records              | p20230703      |  3193543 |         953 | 2023-07-10 17:08:37.146617 |
……

查看索引的统计信息:

http://www.cndba.cn/dave/article/131416

obclient [oceanbase]> select owner,index_name,TABLE_NAME  ,partition_name,NUM_ROWS  ,LAST_ANALYZED  from OCEANBASE.DBA_IND_STATISTICS where owner='cndba';
+-----------+---------------------------+---------------------------+----------------+----------+----------------------------+
| owner     | index_name                | TABLE_NAME                | partition_name | NUM_ROWS | LAST_ANALYZED              |
+-----------+---------------------------+---------------------------+----------------+----------+----------------------------+
| cndba | uid_unique_index          | chat_score                | NULL           |   119013 | 2023-07-10 17:07:38.589751 |
| cndba | uid_unique_index          | chat_violation            | NULL           |     1698 | 2023-07-10 17:07:39.044642 |
| cndba | uid_unique_index          | chat_user                 | NULL           |   828760 | 2023-07-10 17:08:45.162723 |
| cndba | idx_req_id                | chat_req_model            | NULL           |    18982 | 2023-07-10 17:08:45.278139 |
| cndba | uni_uid_url-key           | share_chat                | NULL           |        0 | 2023-07-10 17:08:45.353340 |
| cndba | idx_act                   | chat_bot_list             | NULL           |   420923 | 2023-07-10 17:07:43.205647 |
| cndba | idx_create_time           | chat_bot_base             | NULL           |     5054 | 2023-07-10 17:08:41.096770 |
| cndba | idx_create_time1          | chat_bot_base             | NULL           |     5054 | 2023-07-10 17:08:41.103599 |
| cndba | idx_create_time2          | chat_bot_list             | NULL           |   420923 | 2023-07-10 17:07:43.212634 |
| cndba | idx_support_context       | chat_bot_base             | NULL           |     5054 | 2023-07-10 17:08:41.110763 |
| cndba | idx_real_bot_id           | chat_bot_list             | NULL           |   420923 | 2023-07-10 17:07:43.219261 |
| cndba | idx_uid                   | chat_bot_base             | NULL           |     5054 | 2023-07-10 17:08:41.117820 |
| cndba | idx_uid                   | chat_bot_list             | NULL           |   420923 | 2023-07-10 17:07:43.225805 |
| cndba | idx_create_time           | call_out_record           | NULL           |   449476 | 2023-07-10 17:07:40.802805 |

2 统计信息收集

2.1 直方图说明

直方图是一种特殊类型的列统计信息,通过将数据保存到一系列有序的桶中来描述其列的数据分布特征,优化器可以依据直方图来估算出更准确的行数。

在默认情况下,优化器会认为列的数据是分布均匀的,之后会根据这一特征来进行行数估计,但是在真实的场景中,大多数表的数据分布都是不均匀的,这种情况就需要使用直方图。

在 OceanBase 数据库优化器中,列的直方图信息存储在视图 ALL_TAB_HISTOGRAMS、DBA_TAB_HISTOGRAMS 和 USER_TAB_HISTOGRAMS 中,包含以下信息:

1.直方图的基本信息(包括 tenant_id、table_id、partition_id、column_id)
2.直方图的统计信息类型(信息级别分为 GLOBAL、PARTITION 和 SUBPARTITION)
3.直方图中每个桶累积的数据量(包含当前桶及其之前的桶的总和)
4.直方图中每个桶里面的最大的 Value 值
5.直方图中每个桶里面的最大 Value 值的频次

OceanBase 社区版暂不支持 ALL_TAB_HISTOGRAMS 和 USER_TAB_HISTOGRAMS 视图。

2.1.1 直方图类型

OceanBase 数据库优化器支持三种直方图:频率直方图、Topk 直方图和混合直方图。

1.频率直方图:每个不同的列值对应于直方图的单个桶,要求指定的桶的个数不低于列的 NDV 值(列中不同值)。
2.Topk 直方图:是频率直方图的变体,基于 Lossy Counting 算法,通过取部分数据特征来估算整体的数据分布,要求它所记录的数据数与总数据数的比例不低于 1-(1/bucket_size)。
3.混合直方图:主要通过采集指定的的数据量进行直方图构建,是对频率直方图和 Topk 直方图的功能补充。

2.1.1.1 频率直方图

在频率直方图中,每个不同的列值对应于直方图的单个桶。因为每个值都有自己的专用桶,所以一些桶可能有很多值,而另一些则很少。

频率直方图的类比是对硬币进行分类,例如一个钱袋里面一共有 4 种不同面值(0.1 元、0.2 元、0.5 元、1 元)的 20 枚硬币,我们按照分类将所有 0.1 元的硬币放在第一个桶,所有 0.2 元的硬币放在第二个桶,所有 0.5 元的硬币放在第三个桶,所有 1 元的硬币放在第四个桶,综合频率直方图的特性,要求指定的桶的个数不低于列的 NDV 值。

2.1.1.2 Topk 直方图

Topk 直方图是频率直方图的变体,当我们指定的桶个数不足以装下所有 NDV 时,就会考虑选择使用 Topk 直方图,Topk 直方图本质是忽略频次低的数据,主要考虑频次高的数据分布。

例如,一个钱袋里面一共有 4 种不同面值(0.1 元、0.2 元、0.5 元、1 元)的 100 枚硬币,其中 0.1 元的硬币仅仅只有 1 枚,同时我们只有 3 个桶来装硬币,因此就可以忽略 0.1 元的硬币,只考虑剩下三种硬币的分布。

由于 Topk 直方图是通过取部分数据特征来估算整体的数据分布,因此为了保证误差不会太大,要求 Topk 直方图记录的数据数与总数据数的比例不低于 1–(1/bucket_size);比如上述场景中,指定桶个数为 3,一共有 100 枚硬币,Topk 直方图记录了 99 枚,那么显然 99/100 > 2/3,满足要求。目前 OceanBase 数据库优化器主要通过 Lossy Counting 算法来实现 Topk 直方图。

2.1.1.3 混合直方图

针对于一种数据量很大的大表场景,指定的直方图桶个数低于 NDV 值,同时 Topk 直方图也无法满足最低的数据占比,这个时候就需要一种更加均衡的直方图来描述数据分布的特征,由此引入了混合直方图。

混合直方图主要通过采集指定的的数据量进行直方图构建,与频率直方图和 Topk 直方图的不同的是,一个桶里面可能装多个不同的 Value 值,将采集到的数据量按照桶个数分段,将每一分段内的所有数据都放到对应的一个桶中,达到用更少的桶来描述更大数据量的数据分布,其中桶内的最大的 Value 值将作为 endpoint_value,同时会多一个 endpoint_repeat_cnt 来记录 endpoint_value 的频次。

例如,同样的有 100 枚硬币:0.1 元有 10 枚、0.2 元有 10 枚、0.5 元有 15 枚、1 元有 15 枚、2 元有 25 枚、5 元有 10 枚、10 元有 15 枚,由此计算得出 Topk 直方图覆盖的数据占比是 (25+15+15+15)/100=0.7,而 Topk 覆盖数据占比的最小阈值是 1-1/N =3/4=0.75,未达到该阈值,不满足 Topk 直方图的条件。

2.1.2 直方图的选择策略

OceanBase 数据库优化器根据 NDV、bucket_size 和 p 指标选择直方图。直方图的选择策略如下图所示。

指标含义如下:

1.NDV:指定一个列上不同 Value 值的个数。
2.bucket_size:指定的直方图桶个数,默认为 254。
3.p:Topk 直方图期望的最低百分比阈值,计算公式为 (1—(1/bucket_size)) * 100。如果使用默认值 254,则对应的最低百分比阈值为 99.6。

2.2 手动收集统计信息

OceanBase 数据库优化器主要通过 DBMS_STATS 包 和 ANALYZE 语句两种方式手动收集统计信息。

2.2.1 通过 DBMS_STATS 包

2.2.1.1 参数说明

涉及如下 3 个包:

GATHER_INDEX_STATS 收集索引统计信息。
GATHER_TABLE_STATS 收集表和列的统计信息。
GATHER_SCHEMA_STATS 收集 Schema 中所有对象的统计信息。

关于包具体字段的说明直接参考官网:

https://www.oceanbase.com/docs/common-oceanbase-database-cn-10000000001699698

在使用时重点关注如下几个参数:

1.ownname:Oracle 模式:用户名。MySQL 模式:表所在数据库名称。
2.tabname 表名。
3.indname 索引名。
4.partname 分区名。默认为 NULL。
5.estimate_percent指定使用多少比例的数据计算其分布特征,范围为 [0.000001,100]。 如果指定为 NULL,则使用所有数据。默认是 AUTO_SAMPLE_SIZE,即由优化器内部决定使用多少比例的数据。
6.degree 统计信息收集时的并行度,默认为 NULL。
7.cascade 是否同时收集表的索引统计信息,默认为 TRUE。
8.method_opt 设置列级别的统计信息收集方式(控制直方图)。

直方图的收集通过method_opt 选项来控制,其语法如下:

  FOR ALL [INDEXED | HIDDEN] COLUMNS [size_clause]
| FOR COLUMNS [size clause] column [size_clause] [,column [size_clause]...]

size_clause:
  SIZE integer 
| SIZE REPEAT
| SIZE AUTO
| SIZE SKEWONLY

column:
   column_name
| (column_name [, column_name])

SIZE integer:指定收集列的直方图桶的个数,取值范围为 [1, 2048]。
REPEAT:仅仅只收集被收集过直方图的列的直方图。使用之前收集直方图设置的桶个数。
AUTO:OceanBase 数据库优化器根据列的使用情况,来决定是否收集列的直方图。直方图桶个数使用默认值 254。
SKEWONLY:仅仅只收集数据分布不均匀的列的直方图。直方图桶个数使用默认值 254。

因为收集直方图比较耗时,所以一般都不收集,但如果执行计划不准确,那么则需要收集。

比如method_opt=>’for all columns size 1’ 表示不收集直方图。http://www.cndba.cn/dave/article/131416

2.2.1.2 使用示例

非分区表的统计信息收集

#不收集直方图的场景 
CALL DBMS_STATS.GATHER_TABLE_STATS('test', 't1', method_opt=>'for all columns size 1'); 

#收集直方图的场景并使用默认策略 
CALL DBMS_STATS.GATHER_TABLE_STATS('test', 't1');

收集用户 user 的表 tbl1 的全局级别的统计信息。
CALL dbms_stats.gather_table_stats('user', 'tbl1', granularity=>'GLOBAL', method_opt=>'FOR ALL COLUMNS SIZE AUTO');

收集用户 user 的表 t_part1 的分区级别的统计信息,并行度为 64,只收集数据分布不均匀的列的直方图。
CALL dbms_stats.gather_table_stats('user', 't_part1', degree=>'64', granularity=>'PARTITION', method_opt=>'FOR ALL COLUMNS SIZE SKEWONLY');

收集用户 user 的表 t_subpart1 所有的统计信息,并行度为 128,只收集 50% 的数据,所有的列的直方图都由优化器内部决定。
CALL dbms_stats.gather_table_stats('user', 't_subpart1', degree=>'128', estimate_percent=> '50', granularity=>'ALL', method_opt=>'FOR ALL COLUMNS SIZE AUTO');

分区表的统计信息收集

# 不收集直方图的场景
CALL DBMS_STATS.GATHER_TABLE_STATS('test', 't_part', granularity=>'APPROX_GLOBAL AND PARTITION', method_opt=>'for all columns size 1');

# 收集直方图的场景并使用默认策略
CALL DBMS_STATS.GATHER_TABLE_STATS('test', 't_part', granularity=>'APPROX_GLOBAL AND PARTITION');

Schema(数据库)级别的统计信息收集

没有大表(亿级):
# 不收集直方图的场景
CALL DBMS_STATS.GATHER_SCHEMA_STATS('test', degree=>'16', method_opt=>'for all columns size 1');

# 收集直方图的场景并使用默认策略
CALL DBMS_STATS.GATHER_SCHEMA_STATS('test', degree=>'16');

如果用户下存在超大表(行数超过 1 亿)时,可以选择针对超大表开大并行单独收集,然后锁定超大表的统计信息再使用上述命令收集整个用户的,收集完成后在解锁超大表的统计信息,后续按照增量模式收集,示例如下:

CALL DBMS_STATS.GATHER_TABLE_STATS('test', 'big_table', degree=>128, method_opt=>'for all columns size 1');

CALL DBMS_STATS.LOCK_TABLE_STATS('test','big_table');

CALL DBMS_STATS.GATHER_SCHEMA_STATS('TEST', degree=>'16', method_opt=>'for all columns size 1');

CALL DBMS_STATS.UNLOCK_TABLE_STATS('test','big_table');

2.2.2 通过 ANALYZE 语句

OB Oracle 模式下的 analyze 语法更丰富一下,以为开源只支持 mysql。

我们这里只看MySQL 模式下的 ANALYZE 语法:

ANALYZE TABLE table_name UPDATE HISTOGRAM ON column_name_list WITH INTNUM BUCKETShttp://www.cndba.cn/dave/article/131416

收集表 tbl1 的统计信息,列的桶个数为 30 个。

ANALYZE TABLE tbl1 UPDATE HISTOGRAM ON a, b, c, d WITH 30 BUCKETS;

2.3 自动收集统计信息

2.3.1 自动收集说明

OceanBase 数据库中表的统计信息过期判断标准为,如果当前表增量的 DML 次数(上一次收集统计信息时 DML 次数到本次收集统计信息期间发生的增/删/改总次数)超过设置的阈值时就会过期。阈值的默认值是 10%,阈值可以通过 peres 调整设置。http://www.cndba.cn/dave/article/131416

系统表和非分区用户表的自动收集策略:

1.如果表没有 GLOBAL 级别的统计信息,自动收集统计信息。
2.如果表有 GLOBAL 级别的统计信息,但是统计信息已经过期,则自动收集统计信息。否则,OceanBase 数据库优化器不会自动收集统计信息。

分区用户表的自动收集策略:

1.如果表没有任何统计信息,自动收集所有的统计信息。
2.如果表有分区级别的统计信息,但是没有 GLOBAL 级别统计信息,则采用增量的方式自动收集统计信息。
3.如果表有 GLOBAL 级别统计信息,但是已经过期,则自动收集所有的统计信息。
4.如果表有 GLOBAL 级别统计信息,但是没有全部过期,只是部分分区的统计信息过期,则自动收集统计信息过期的分区统计信息,同时采用增量的方式推导 GLOBAL 级别统计信息。

2.3.2 查看自动收集任务

OceanBase 优化器通过基于 DBMS_SCHEDULER 系统包实现的 MAINTENANCE WINDOW 来实现每日的自动统计信息收集,从而保证统计信息的不断迭代更新。

OceanBase 数据库定义 MAINTENANCE WINDOW 为周一到周日有 7 个自动统计信息收集任务,周一到周五的任务开始时间为 22:00,最大收集时长为 4 小时,周六和周日的开始时间为 6:00,最大收集时长为 20 小时。

obclient [oceanbase]> select JOB_NAME ,START_DATE ,REPEAT_INTERVAL ,MAX_RUN_DURATION  from OCEANBASE.DBA_SCHEDULER_JOBS where JOB_NAME  like '%WINDOW';
+------------------+----------------------------+-------------------------+------------------+
| JOB_NAME         | START_DATE                 | REPEAT_INTERVAL         | MAX_RUN_DURATION |
+------------------+----------------------------+-------------------------+------------------+
| FRIDAY_WINDOW    | 2023-06-16 22:00:00.000000 | FREQ=WEEKLY; INTERVAL=1 |            14400 |
| MONDAY_WINDOW    | 2023-06-19 22:00:00.000000 | FREQ=WEEKLY; INTERVAL=1 |            14400 |
| SATURDAY_WINDOW  | 2023-06-17 06:00:00.000000 | FREQ=WEEKLY; INTERVAL=1 |            72000 |
| SUNDAY_WINDOW    | 2023-06-18 06:00:00.000000 | FREQ=WEEKLY; INTERVAL=1 |            72000 |
| THURSDAY_WINDOW  | 2023-06-15 22:00:00.000000 | FREQ=WEEKLY; INTERVAL=1 |            14400 |
| TUESDAY_WINDOW   | 2023-06-20 22:00:00.000000 | FREQ=WEEKLY; INTERVAL=1 |            14400 |
| WEDNESDAY_WINDOW | 2023-06-14 22:00:00.000000 | FREQ=WEEKLY; INTERVAL=1 |            14400 |
+------------------+----------------------------+-------------------------+------------------+
7 rows in set (0.007 sec)

可以通过如下函数管理和配置 JOB:

DBMS_SCHEDULER.DISABLE($window_name);
DBMS_SCHEDULER.ENABLE($window_name);
DBMS_SCHEDULER.SET_ATTRIBUTE();

http://www.cndba.cn/dave/article/131416

2.3.3 DML STATS

DML STATS 用于记录一张表做增、删、改的次数。

表的 DML STATS 对于自动统计信息收集有着至关重要的作用,它决定了一张表是否需要再次收集统计信息。数据库中的表的数据信息并不是每天都会更新,因此对于不存在数据变化或者数据变化在预期范围内的表,不需要再次收集统计信息,这样可以提升自动统计信息收集任务的执行效率。

DML STATS 信息的相关视图和表信息:http://www.cndba.cn/dave/article/131416

1.OCEANBASE.GV$DML_STATS、OCEANBASE.V$DML_STATS:查询虚表中记录的表的DML STATS
2.OCEANBASE.DBA_TAB_MODIFICATIONS:查询表中所有的 DML STATS

2.4 在线统计信息收集

在线统计信息收集指在执行 INSERT 插入时,数据库优化器就可以收集统计信息,不用手动调用系统包。在批量导入数据的过程中,可以实时收集统计信息,不需要额外的发起收集任务,减少了运维操作,提高统计信息收集性能。

OceanBase 使用 GATHER_OPTIMIZER_STATISTICS/NO_GATHER_OPTIMIZER_STATISTICS Hint 和系统变量 _optimizer_gather_stats_on_load(默认开启)进行在线统计信息收集,同时也可以使用旁路导入功能的 APPEND Hint 实现在线统计信息收集。

obclient [oceanbase]> show variables like '%_optimizer_gather_stats_on_load%';
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| _optimizer_gather_stats_on_load | ON    |
+---------------------------------+-------+
1 row in set (0.002 sec)

2.4.1 CREATE TABLE…AS SELECT(即 CTAS)

在系统变量 _optimizer_gather_stats_on_load 为 True 时,CTAS 默认启动在线收集统计信息功能。

如果需要禁用该功能,可以使用 NO_GATHER_OPTIMIZER_STATISTICS Hint,示例如下:

CREATE TABLE table_name AS SELECT /+NO_GATHER_OPTIMIZER_STATISTICS/* FROM…

2.4.2 INSERT INTO

在系统变量 _optimizer_gather_stats_on_load 为 True 时,使用 GATHER_OPTIMIZER_STATISTICS Hint 或者 APPEND Hint 启动在线收集统计信息功能。

示例如下:

INSERT /+GATHER_OPTIMIZER_STATISTICS/ INTO table_name SELECT * FROM table_name

http://www.cndba.cn/dave/article/131416

2.4.3 PDML

通过 ENABLE_PARALLEL_DML Hint 或者通过 ALTER SESSION ENABLE PARALLEL DML; 设置系统并行模式的方式让插入操作以并行的方式进行。

示例如下:

CREATE TABLE t1(c1 INT) PARTITION BY HASH(c1) PARTITIONS 4;
CREATE TABLE t2(c1 INT) PARTITION BY HASH(c1) PARTITIONS 4;
INSERT INTO t1 VALUES (1),(2),(3),(4);

obclient> EXPLAIN INSERT /*+ENABLE_PARALLEL_DML PARALLEL(4)*/ INTO t2 SELECT * FROM t1;

查看统计信息:

obclient [oceanbase]> select owner,TABLE_NAME ,partition_name,NUM_ROWS ,AVG_ROW_LEN ,LAST_ANALYZED  from OCEANBASE.DBA_TAB_STATISTICS where owner='cndba';
+-----------+--------------------------------+----------------+----------+-------------+----------------------------+
| owner     | TABLE_NAME                     | partition_name | NUM_ROWS | AVG_ROW_LEN | LAST_ANALYZED              |
+-----------+--------------------------------+----------------+----------+-------------+----------------------------+
| cndba | chat_req_records_transit       | NULL           |        0 |           0 | 2023-07-10 17:07:38.295836 |
| cndba | chat_record_tree               | NULL           |       29 |         156 | 2023-07-10 17:07:38.389382 |
| cndba | chat_score                     | NULL           |   119013 |         100 | 2023-07-10 17:07:38.569771 |
| cndba | freeze_user_record             | NULL           |   457272 |          80 | 2023-07-10 17:07:38.983850 |
| cndba | chat_violation                 | NULL           |     1698 |         100 | 2023-07-10 17:07:39.032010 |
| cndba | test_data_industry_copy1       | NULL           |        0 |           0 | 2023-07-10 17:07:39.067542 |
| cndba | chat_complaint                 | NULL           |        0 |           0 | 2023-07-10 17:07:39.104315 |
| cndba | chat_resp_records_transit      | NULL           |        0 |           0 | 2023-07-10 17:07:39.137004 |
| cndba | ow_survey                      | NULL           |    10648 |         100 | 2023-07-10 17:07:39.212023 |
| cndba | chat_special_uid               | NULL           |      392 |         133 | 2023-07-10 17:07:39.244743 |
| cndba | ow_register                    | NULL           |        1 |         298 | 2023-07-10 17:07:39.307249 |
| cndba | sparkdesk_industry             | NULL           |       11 |          77 | 2023-07-10 17:07:39.344826 |
| cndba | chat_bot_market                | NULL           |     2078 |         714 | 2023-07-10 17:07:39.427636 |
| cndba | bot_type_list                  | NULL           |       18 |         151 | 2023-07-10 17:07:39.513939 |
| cndba | call_out_record                | NULL           |   449476 |         351 | 2023-07-10 17:07:40.788247 |
| cndba | chat_properties                | NULL           |        2 |         129 | 2023-07-10 17:07:40.850132 |
| cndba | screen                         | NULL           |        0 |           0 | 2023-07-10 17:07:40.899464 |
| cndba | test_data_industry             | NULL           |       11 |          77 | 2023-07-10 17:07:40.932092 |
| cndba | chat_token_records             | NULL           | 37031506 |         183 | 2023-07-10 17:07:42.644534 |
| cndba | manage_user                    | NULL           |        0 |           0 | 2023-07-10 17:07:42.690298 |
| cndba | chat_bot_list                  | NULL           |   420923 |         498 | 2023-07-10 17:07:43.185654 |
| cndba | chat_vip_users                 | NULL           |    33118 |         212 | 2023-07-10 17:07:43.352218 |
| cndba | chat_appointment_log           | NULL           |     4126 |         110 | 2023-07-10 17:07:43.408195 |
| cndba | prompt_type                    | NULL           |        6 |          61 | 2023-07-10 17:07:43.443032 |
| cndba | test_data_pv_uv                | NULL           |        7 |          76 | 2023-07-10 17:07:43.470428 |
| cndba | chat_bot_remove                | NULL           |      151 |         615 | 2023-07-10 17:07:43.511825 |
| cndba | chat_resp_records              | NULL           | 17942553 |         957 | 2023-07-10 17:08:37.146617 |
| cndba | chat_resp_records              | p20230410      |        0 |           0 | 2023-07-10 17:08:37.146617 |
| cndba | chat_resp_records              | p20230417      |        0 |           0 | 2023-07-10 17:08:37.146617 |
| cndba | chat_resp_records              | p20230424      |        0 |           0 | 2023-07-10 17:08:37.146617 |
| cndba | chat_resp_records              | p20230501      |        0 |           0 | 2023-07-10 17:08:37.146617 |
| cndba | chat_resp_records              | p20230508      |        0 |           0 | 2023-07-10 17:08:37.146617 |
| cndba | chat_resp_records              | p20230515      |        0 |           0 | 2023-07-10 17:08:37.146617 |
| cndba | chat_resp_records              | p20230522      |        0 |           0 | 2023-07-10 17:08:37.146617 |
| cndba | chat_resp_records              | p20230529      |        0 |           0 | 2023-07-10 17:08:37.146617 |
| cndba | chat_resp_records              | p20230605      |        0 |           0 | 2023-07-10 17:08:37.146617 |
| cndba | chat_resp_records              | p20230612      |  3980882 |         991 | 2023-07-10 17:08:37.146617 |
| cndba | chat_resp_records              | p20230619      |  4479632 |         940 | 2023-07-10 17:08:37.146617 |
| cndba | chat_resp_records              | p20230626      |  3134480 |         943 | 2023-07-10 17:08:37.146617 |
| cndba | chat_resp_records              | p20230703      |  3193543 |         953 | 2023-07-10 17:08:37.146617 |
……

3 统计信息管理

统计信息的管理功能是 OceanBase 的优化器兼容 Oracle 的 DBMS_STATS 包相关统计信息管理函数而实现的相关功能,主要包括统计信息删除、统计信息设置、统计信息导入导出、统计信息锁定、统计信息历史版本管理及统计信息收集策略 Prefs 配置等功能模块。

我们这里只看 2 个常用的功能删除和锁定。

3.1 删除统计信息

OceanBase 数据库调用 DBMS_STATS 包相关的存储过程 PROCEDURE 去删除保存在内部表中收集的统计信息。

目前支持如下三种删除统计信息的方式:

1.使用存储过程 delete_table_stats 删除表级的统计信息。
2.使用存储过程 delete_column_stats 删除列级的统计信息。
3.使用存储过程 delete_schema_stats 删除 Schema 下所有表的统计信息。
4.使用存储过程 delete_index_stats 删除索引统计信息.

注:在 OB 的 mysql 模式里,owner 和 scheme 就是数据库名称。

操作示例:删除表的所有统计信息。

obclient [oceanbase]> select owner,TABLE_NAME ,partition_name,NUM_ROWS ,AVG_ROW_LEN ,LAST_ANALYZED  from OCEANBASE.DBA_TAB_STATISTICS where table_name='visit_log';
+-----------+------------+----------------+----------+-------------+----------------------------+
| owner     | TABLE_NAME | partition_name | NUM_ROWS | AVG_ROW_LEN | LAST_ANALYZED              |
+-----------+------------+----------------+----------+-------------+----------------------------+
| cndba | visit_log  | NULL           |        7 |         144 | 2023-07-10 17:09:18.793960 |
+-----------+------------+----------------+----------+-------------+----------------------------+
1 row in set (0.044 sec)

obclient [oceanbase]> CALL dbms_stats.delete_table_stats('cndba', 'visit_log');
Query OK, 0 rows affected (0.371 sec)

obclient [oceanbase]> select owner,TABLE_NAME ,partition_name,NUM_ROWS ,AVG_ROW_LEN ,LAST_ANALYZED  from OCEANBASE.DBA_TAB_STATISTICS where table_name='visit_log';
+-----------+------------+----------------+----------+-------------+---------------+
| owner     | TABLE_NAME | partition_name | NUM_ROWS | AVG_ROW_LEN | LAST_ANALYZED |
+-----------+------------+----------------+----------+-------------+---------------+
| cndba | visit_log  | NULL           |     NULL |        NULL | NULL          |
+-----------+------------+----------------+----------+-------------+---------------+
1 row in set (0.005 sec)

obclient [oceanbase]> CALL DBMS_STATS.GATHER_TABLE_STATS('cndba', 'visit_log', method_opt=>'for all columns size 1'); 
Query OK, 0 rows affected (0.095 sec)

obclient [oceanbase]> select owner,TABLE_NAME ,partition_name,NUM_ROWS ,AVG_ROW_LEN ,LAST_ANALYZED  from OCEANBASE.DBA_TAB_STATISTICS where table_name='visit_log';
+-----------+------------+----------------+----------+-------------+----------------------------+
| owner     | TABLE_NAME | partition_name | NUM_ROWS | AVG_ROW_LEN | LAST_ANALYZED              |
+-----------+------------+----------------+----------+-------------+----------------------------+
| cndba | visit_log  | NULL           |        7 |         144 | 2023-07-12 19:58:52.080771 |
+-----------+------------+----------------+----------+-------------+----------------------------+
1 row in set (0.005 sec)

obclient [oceanbase]>

3.2 锁定 / 解锁统计信息

统计信息的锁定功能主要用于锁死统计信息,防止统计信息更新,以保证统计信息的稳定性。

例如,如果想指定某一张表不收集统计信息,就可以提前上锁,这样计划生成的时候就会采取其他方式获取统计信息(动态采样等)。又如,对于一张数据稳定的表,我们不需要经常去收集它的统计信息,因此就可以提前上锁。

三种锁定统计信息的方式:

1.使用存储过程 lock_table_stats 锁定某个表的统计信息。
2.使用存储过程 lock_partition_stats 锁定某个分区的统计信息。
3.使用存储过程 lock_schema_stats 锁定某个 Schema 下所有表的统计信息。

三种解锁统计信息的方式:

http://www.cndba.cn/dave/article/131416

1.使用存储过程 unlock_table_stats 解锁某个表的统计信息。
2.使用存储过程 unlock_partition_stats 解锁某个分区的统计信息。
3.使用存储过程 unlock_schema_stats 解锁某个 Schema 下所有表的统计信息。http://www.cndba.cn/dave/article/131416

操作示例:

obclient [oceanbase]> select owner,TABLE_NAME ,partition_name,NUM_ROWS ,AVG_ROW_LEN ,LAST_ANALYZED,stattype_locked  from OCEANBASE.DBA_TAB_STATISTICS where table_name='visit_log';
+-----------+------------+----------------+----------+-------------+----------------------------+-----------------+
| owner     | TABLE_NAME | partition_name | NUM_ROWS | AVG_ROW_LEN | LAST_ANALYZED              | stattype_locked |
+-----------+------------+----------------+----------+-------------+----------------------------+-----------------+
| cndba | visit_log  | NULL           |        7 |         144 | 2023-07-12 19:58:52.080771 | NULL            |
+-----------+------------+----------------+----------+-------------+----------------------------+-----------------+
1 row in set (0.043 sec)

obclient [oceanbase]> CALL dbms_stats.lock_table_stats('cndba', 'visit_log');
Query OK, 0 rows affected (0.009 sec)

obclient [oceanbase]> select owner,TABLE_NAME ,partition_name,NUM_ROWS ,AVG_ROW_LEN ,LAST_ANALYZED,stattype_locked  from OCEANBASE.DBA_TAB_STATISTICS where table_name='visit_log';
+-----------+------------+----------------+----------+-------------+----------------------------+-----------------+
| owner     | TABLE_NAME | partition_name | NUM_ROWS | AVG_ROW_LEN | LAST_ANALYZED              | stattype_locked |
+-----------+------------+----------------+----------+-------------+----------------------------+-----------------+
| cndba | visit_log  | NULL           |        7 |         144 | 2023-07-12 19:58:52.080771 | ALL             |
+-----------+------------+----------------+----------+-------------+----------------------------+-----------------+
1 row in set (0.005 sec)

obclient [oceanbase]> CALL dbms_stats.unlock_table_stats('cndba', 'visit_log');
Query OK, 0 rows affected (0.009 sec)

obclient [oceanbase]> select owner,TABLE_NAME ,partition_name,NUM_ROWS ,AVG_ROW_LEN ,LAST_ANALYZED,stattype_locked  from OCEANBASE.DBA_TAB_STATISTICS where table_name='visit_log';
+-----------+------------+----------------+----------+-------------+----------------------------+-----------------+
| owner     | TABLE_NAME | partition_name | NUM_ROWS | AVG_ROW_LEN | LAST_ANALYZED              | stattype_locked |
+-----------+------------+----------------+----------+-------------+----------------------------+-----------------+
| cndba | visit_log  | NULL           |        7 |         144 | 2023-07-12 19:58:52.080771 | NULL            |
+-----------+------------+----------------+----------+-------------+----------------------------+-----------------+
1 row in set (0.005 sec)

obclient [oceanbase]>

注:本文根据官网手册整理

版权声明:本文为博主原创文章,未经博主允许不得转载。

用户评论
* 以下用户言论只代表其个人观点,不代表CNDBA社区的观点或立场
dave

dave

关注

人的一生应该是这样度过的:当他回首往事的时候,他不会因为虚度年华而悔恨,也不会因为碌碌无为而羞耻;这样,在临死的时候,他就能够说:“我的整个生命和全部精力,都已经献给世界上最壮丽的事业....."

  • 2261
    原创
  • 3
    翻译
  • 578
    转载
  • 191
    评论
  • 访问:7966781次
  • 积分:4346
  • 等级:核心会员
  • 排名:第1名
精华文章
    最新问题
    查看更多+
    热门文章
      热门用户
      推荐用户
        Copyright © 2016 All Rights Reserved. Powered by CNDBA · 皖ICP备2022006297号-1·

        QQ交流群

        注册联系QQ