达梦统计信息

统计信息

统计信息概述

统计信息是数据库中关于表和索引数据的元信息,用于描述数据的分布、唯一性、大小等特征。数据库优化器依赖统计信息来选择最优的执行计划。统计信息对于 CBO(基于代价的优化器)生成执行计划具有直接影响。

收集统计信息

dm收集统计信息的三种方法:

• 使用dbms_stats包收集

• 使用stat on语句收集

• 使用sp_stat函数收集

--dbms_stats 支持对模式下对象、单个表、单个索引收集统计信息,指定采样率

dbms_stats.gather_table_stats('DMTEST','T_TESTTAB',ESTIMATE_PERCENT=>100);

--查询sp_stat相关的函数

select name from v$ifun t where name like 'SP%_STAT%_INIT';

--stat 语句支持对表、索引、列收集统计信息

stat 100 on dmtest.t_testtab(userid);

DM 收集统计信息的方法分为手动收集和自动收集。

手动收集

--收集指定用户下所有表所有列的统计信息:

DBMS_STATS.GATHER_SCHEMA_STATS('username',100,TRUE,'FOR ALL COLUMNS SIZE AUTO');

--收集指定用户下所有索引的统计信息:

DBMS_STATS.GATHER_SCHEMA_STATS('usename',1.0,TRUE,'FOR ALL INDEXED SIZE AUTO');

--或 收集单个索引统计信息:

DBMS_STATS.GATHER_INDEX_STATS('username','IDX_T2_X');

--收集指定用户下某表统计信息:

DBMS_STATS.GATHER_TABLE_STATS('username','table_name',null,100,TRUE,'FOR ALL COLUMNS SIZE AUTO');

--收集某表某列的统计信息:

STAT 100 ON table_name(column_name);

自动收集

DM支持统计信息的自动收集,当全表数据量变化超过设定阈值后可自动更新统计信息

--打开表数据量监控开关,参数值为 1 时监控所有表,2 时仅监控配置表

SP_SET_PARA_VALUE(1,'AUTO_STAT_OBJ',2);

--设置 SYSDBA.T 表数据变化率超过 15% 时触发自动更新统计信息

DBMS_STATS.SET_TABLE_PREFS('SYSDBA','T','STALE_PERCENT',15);

--配置自动收集统计信息触发时机

SP_CREATE_AUTO_STAT_TRIGGER(1, 1, 1, 1,'14:36', '2020/3/31',60,1);

/*

函数各参数介绍

SP_CREATE_AUTO_STAT_TRIGGER(

TYPE INT, --间隔类型,默认为天

FREQ_INTERVAL INT, --间隔频率,默认 1

FREQ_SUB_INTERVAL INT, --间隔频率,与 FREQ_INTERVAL 配合使用

FREQ_MINUTE_INTERVAL INT, --间隔分钟,默认为 1440

STARTTIME VARCHAR(128), --开始时间,默认为 22:00

DURING_START_DATE VARCHAR(128), --重复执行的起始时间,默认 1900/1/1

MAX_RUN_DURATION INT, --允许的最长执行时间(秒),默认不限制

ENABLE INT --0 关闭,1 启用 --默认为 1

);

*/

统计信息的基本操作

查看统计信息

--用于经过 GATHER_TABLE_STATS、GATHER_INDEX_STATS 或 GATHER_SCHEMA_STATS 收集之后展示。

dbms_stats.table_stats_show('模式名','表名');

--用于经过 GATHER_TABLE_STATS、GATHER_INDEX_STATS 或 GATHER_SCHEMA_STATS 收集之后展示。 返回两个结果集:一个是索引的统计信息;另一个是直方图的统计信息。

dbms_stats.index_stats_show('模式名','索引名');

--用于经过 GATHER_TABLE_STATS、GATHER_INDEX_STATS 或 GATHER_SCHEMA_STATS 收集之后展示。

dbms_stats.COLUMN_STATS_SHOW('模式名','表名','列名');

更新统计信息

--更新已有统计信息

DBMS_STATS.UPDATE_ALL_STATS();

删除统计信息

--表

DBMS_STATS.DELETE_TABLE_STATS('模式名','表名','分区名',...);

--模式

DBMS_STATS.DELETE_SCHMA_STATS('模式名','','',...);

--索引

DBMS_STATS.DELETE_INDEX_STATS('模式名','索引名','分区表名',...);

--字段

DBMS_STATS.DELETE_COLUMN_STATS('模式名','表名','列名','分区表名',...);

测试用例

表数据量大幅变化后未更新统计信息

创建测试表并插入初始数据

CREATE TABLE test_employees (

emp_id INT,

dept_id INT,

emp_name VARCHAR(50)

);

-- 插入 1000 条数据,dept_id 均匀分布(1~10)

INSERT INTO test_employees

SELECT LEVEL, MOD(LEVEL, 10) + 1, 'EMP_' || LEVEL

FROM DUAL CONNECT BY LEVEL <= 1000;

-- 创建非唯一索引

CREATE INDEX idx_dept ON test_employees(dept_id);

收集统计信息

DBMS_STATS.GATHER_TABLE_STATS('SYSDBA', 'TEST_EMPLOYEES', NULL, 100);

查看执行计划(正确使用索引)

EXPLAIN SELECT * FROM test_employees WHERE dept_id = 5;

预期:INDEX RANGE SCAN(dept_id=5 筛选约 100 行)

插入倾斜数据(不更新统计信息)

-- 插入 100000 条数据,dept_id 全部为 5

INSERT INTO test_employees

SELECT 1000 + LEVEL, 5, 'EMP_' || (1000 + LEVEL)

FROM DUAL CONNECT BY LEVEL <= 100000;

再次执行查询(CBO 错误选择索引扫描)

EXPLAIN SELECT * FROM test_employees WHERE dept_id = 5;

-- 实际结果:INDEX RANGE SCAN

-- 预期问题:CBO 仍认为 dept_id=5 仅有约 100 行,实际有 100100 行。

更新统计信息并验证

-- 预期修正:TABLE FULL SCAN(因 dept_id=5 数据量过大,全表扫描更优)

索引创建后未更新统计信息

创建测试表并插入数据

CREATE TABLE test_products (

product_id INT,

product_name VARCHAR(50),

category_id INT

);

INSERT INTO test_products

SELECT LEVEL, 'Product_' || LEVEL, MOD(LEVEL, 10)

FROM DUAL CONNECT BY LEVEL <= 100000;

收集统计信息

DBMS_STATS.GATHER_TABLE_STATS('SYSDBA', 'TEST_PRODUCTS', NULL, 100);

创建索引但不更新统计信息

CREATE INDEX idx_category_id ON test_products(category_id);

查看执行计划

EXPLAIN SELECT * FROM test_products WHERE category_id = 5;

--预期选择全表扫描,结果是优化器正确选择索引扫描

更新统计信息后验证

--优化器依然正确选择索引扫描

更多详细资料可前往达梦社区:https://eco.dameng.com

相关推荐
Lethehong6 分钟前
多模融合时代,文档数据库正在被重新定义——金仓数据库如何构建新一代文档数据底座
数据库·金融·能源·政务
一个处女座的程序猿O(∩_∩)O7 分钟前
多模融合:金仓数据库重新定义文档处理能力
数据库
野生技术架构师14 分钟前
MySQL深度分页优化实战:从踩坑到落地的全攻略
数据库·mysql
e***985717 分钟前
MySQL数据可视化实战:从查询到图表全攻略
数据库·mysql·信息可视化
二哈喇子!22 分钟前
数据库如何建表
数据库·sql·mysql
计算机网恋22 分钟前
思源笔记使用S3同步(阿里云OSS)
数据库·笔记·阿里云
学嵌入式的小杨同学24 分钟前
【嵌入式 C 语言实战】手动实现字符串四大核心函数(strcpy/strcat/strlen/strcmp)
c语言·开发语言·前端·javascript·数据结构·数据库·算法
计算机网恋29 分钟前
部署Umami监测网站访问情况(更改数据库为MariaDB数据库)
android·数据库·mariadb
Maggie_ssss_supp29 分钟前
LINUX-MySQL单表查询
数据库·mysql
程序边界34 分钟前
深度体验金仓时序数据库:从“存储与分析困局“到低成本落地的实战记录
数据库·时序数据库