OceanBase 数据库优化器主要通过 DBMS_STATS 包 和 ANALYZE 语句两种方式手动收集统计信息。
通过 DBMS_STATS 包收集统计信息
OceanBase 数据库优化器支持利用 DBMS_STATS 包收集表级、Schema 级别的统计信息和索引统计信息,分别通过调用存储过程 gather_table_stats、gather_schema_stats 和 gather_index_stats 来完成。
PROCEDURE gather_table_stats (
ownname VARCHAR2,
tabname VARCHAR2,
partname VARCHAR2 DEFAULT NULL,
estimate_percent NUMBER DEFAULT AUTO_SAMPLE_SIZE,
block_sample BOOLEAN DEFAULT FALSE,
method_opt VARCHAR2 DEFAULT DEFAULT_METHOD_OPT,
degree NUMBER DEFAULT NULL,
granularity VARCHAR2 DEFAULT DEFAULT_GRANULARITY,
cascade BOOLEAN DEFAULT NULL,
stattab VARCHAR2 DEFAULT NULL,
statid VARCHAR2 DEFAULT NULL,
statown VARCHAR2 DEFAULT NULL,
no_invalidate BOOLEAN DEFAULT FALSE,
stattype VARCHAR2 DEFAULT 'DATA',
force BOOLEAN DEFAULT FALSE
);
PROCEDURE gather_schema_stats (
ownname VARCHAR2,
estimate_percent NUMBER DEFAULT AUTO_SAMPLE_SIZE,
block_sample BOOLEAN DEFAULT FALSE,
method_opt VARCHAR2 DEFAULT DEFAULT_METHOD_OPT,
degree NUMBER DEFAULT NULL,
granularity VARCHAR2 DEFAULT DEFAULT_GRANULARITY,
cascade BOOLEAN DEFAULT NULL,
stattab VARCHAR2 DEFAULT NULL,
statid VARCHAR2 DEFAULT NULL,
statown VARCHAR2 DEFAULT NULL,
no_invalidate BOOLEAN DEFAULT FALSE,
stattype VARCHAR2 DEFAULT 'DATA',
force BOOLEAN DEFAULT FALSE
);
PROCEDURE gather_index_stats (
ownname VARCHAR2,
indname VARCHAR2,
partname VARCHAR2 DEFAULT NULL,
estimate_percent NUMBER DEFAULT AUTO_SAMPLE_SIZE,
stattab VARCHAR2 DEFAULT NULL,
statid VARCHAR2 DEFAULT NULL,
statown VARCHAR2 DEFAULT NULL,
degree NUMBER DEFAULT NULL,
granularity VARCHAR2 DEFAULT DEFAULT_GRANULARITY,
no_invalidate BOOLEAN DEFAULT FALSE,
force BOOLEAN DEFAULT FALSE,
tabname VARCHAR2 DEFAULT NULL
);
参数解释如下表所示。
| 参数 | 解释 |
|---|---|
| ownname | 表所在数据库名称。 |
| tabname | 表名。 |
| indname | 索引名。 |
| partname | 分区名。默认为 NULL。 |
| estimate_percent | 指定使用多少比例的数据计算其分布特征,范围为 [0.000001,100]。 如果指定为 NULL,则使用所有数据。默认是 AUTO_SAMPLE_SIZE,即由优化器内部决定使用多少比例的数据。 |
| block_sample | 是否使用块采样代替行采样,默认为 FALSE。 |
| method_opt | 设置列级别的统计信息收集方式。详细信息,请参见 method_opt。 |
| degree | 统计信息收集时的并行度,默认为 NULL。 |
| granularity | 统计信息收集时的分区粒度。 目前支持以下几种设置:
|
| cascade | 是否同时收集表的索引统计信息,默认为 TRUE。 |
| stattab | 该参数暂未实现,不可用。 |
| statid | 该参数暂未实现,不可用。 |
| statown | 该参数暂未实现,不可用。 |
| no_invalidate | 该参数暂未实现,不可用。 |
| stattype | 该参数暂未实现,不可用。 |
| force | 是否强制收集信息,并忽略锁的状态,默认为 FALSE。 |
method_opt
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。 |
此外,DBMS_STATS 包还提供了 GATHER_DATABASE_STATS_JOB_PROC 来收集整个数据库所有表的统计信息,所有收集策略都会采用默认配置的 Prefs,关于设置 Prefs 的详细信息,请参见 收集策略配置项(Prefs)管理功能。
PROCEDURE GATHER_DATABASE_STATS_JOB_PROC();
示例
DBMS_STATS 包收集统计信息的相关示例如下:
收集用户
user的表tbl1的全局级别的统计信息,所有列的桶个数设定为 128。CALL dbms_stats.gather_table_stats('user', 'tbl1', granularity=>'GLOBAL', method_opt=>'FOR ALL COLUMNS SIZE 128');收集用户
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');
表级和索引统计信息收集策略 GRANULARITY 的关联
默认情况下,在收集表统计信息的同时也会收集表上所有索引统计信息,由于索引表上的部分统计信息是可以通过基表的统计信息得到的,包括行数、平均行长(通过对应的几个列计算)等,因此可以加速统计信息的获取,也可以避免二次扫描全表数据。对于本地索引和全局索引两者在 GRANULARITY 上有所区别,如下表所示。
| 指定分区 | GRANULARITY | 全局索引 | 本地索引 |
|---|---|---|---|
| 否 | ALL | GLOBAL 级别 | ALL |
| 否 | AUTO | GLOBAL 级别 | AUTO |
| 否 | DEFAULT | GLOBAL 级别 | DEFAULT |
| 否 | GLOBAL AND PARTITION | GLOBAL 级别 | GLOBAL AND PARTITION |
| 否 | APPROX_GLOBAL AND PARTITION | GLOBAL 级别 | APPROX_GLOBAL AND PARTITION |
| 否 | GLOBAL | GLOBAL 级别 | GLOBAL |
| 否 | PARTITION | GLOBAL 级别 | PARTITION |
| 否 | SUBPARTITION | 不收集 | SUBPARTITION |
| 是 | ALL | GLOBAL 级别 | ALL |
| 是 | AUTO | GLOBAL 级别 | AUTO |
| 是 | DEFAULT | GLOBAL 级别 | DEFAULT |
| 是 | GLOBAL AND PARTITION | GLOBAL 级别 | GLOBAL AND PARTITION |
| 是 | APPROX_GLOBAL AND PARTITION | 不收集 | APPROX_GLOBAL AND PARTITION |
| 是 | GLOBAL | GLOBAL 级别 | GLOBAL |
| 是 | PARTITION | 不收集 | PARTITION |
| 是 | SUBPARTITION | 不收集 | SUBPARTITION |
通过 ANALYZE 语句收集统计信息
ANALYZE 语法如下:
analyze_stmt:
ANALYZE TABLE table_name UPDATE HISTOGRAM ON column_name_list WITH INTNUM BUCKETS
当 Session 变量 enable_sql_extension 为 TRUE 的时候,可以使用 Oracle 模式的语法,即 OceanBase 数据库为 MySQL 模式提供的扩展语法。
analyze_stmt:
ANALYZE TABLE table_name [use_partition] analyze_statistics_clause
ANALYZE 语句统计信息收集示例如下:
收集表
tbl1的统计信息,列的桶个数为 30 个。ANALYZE TABLE tbl1 UPDATE HISTOGRAM ON a, b, c, d WITH 30 BUCKETS;在 MySQL 模式下使用 Oracle 模式的语法收集用户
test的表tbl1的统计信息,所有列的桶个数设定为 128。ALTER SYSTEM SET ENABLE_SQL_EXTENSION = TRUE; ANALYZE TABLE tbl1 COMPUTE STATISTICS FOR ALL COLUMNS SIZE 128;




