本文于 6 天前发布,最后更新于 2 天前
一、前言
对象统计信息描述数据是如何在数据库中存储的。统计信息是优化器的代价计算的依据,可以帮助优化器较精确地估算成本,对执行计划的选择起着至关重要的作用。
达梦数据库的统计信息分三种类型:表统计信息、列统计信息、索引统计信息。通过直方图来表示。统计信息生成过程分以下三个步骤:
- 确定采样的数据:根据数据对象,确定需要分析哪些数据。
- 表:计算表的行数、所占的页数目、平均记录长度
- 列:统计列数据的分布情况
- 索引:统计索引列的数据分布情况
- 确定采样率
- 根据数据对象的大小,通过内部算法,确定数据的采样率。采样率与数据量成反比。
- 生成直方图
- 有两种类型的直方图:频率直方图和等高直方图。根据算法分析表的数据分布特征,确定直方图的类型。频率直方图的每个桶(保存统计信息的对象)的高度不同,等高直方图每个桶的高度相同。例如,对列生成统计信息,当列值分布比较均匀时,会采用等高直方图,否则,采用频率直方图。
在执行查询时,如果数据对象存在统计信息,代价算法可以根据统计信息中的数据,比较精确地计算出操作所需花费的成本,以此来确定连接方式、对象访问路径、连接顺序,选择最优的执行计划。
用户也可以通过修改 OPTIMIZER_DYNAMIC_SAMPLING 参数值在缺乏统计信息时进行动态统计信息收集。
二、收集统计信息
--收集全库统计信息
CALL SP_DB_STAT_INIT ();
--收集指定用户下所有表所有列的统计信息:
DBMS_STATS.GATHER_SCHEMA_STATS('OWNNAME',100,TRUE,'FOR ALL COLUMNS SIZE AUTO');
--收集指定用户下所有索引的统计信息:
DBMS_STATS.GATHER_SCHEMA_STATS('OWNNAME', 1.0, TRUE, 'FOR ALL INDEXED SIZE AUTO');
--或 收集单个索引统计信息:
DBMS_STATS.GATHER_INDEX_STATS('OWNNAME','INDNAME');
--收集指定用户下某表统计信息:
DBMS_STATS.GATHER_TABLE_STATS('OWNNAME','TABNAME',NULL,100,TRUE,'FOR ALL COLUMNS SIZE AUTO');
--收集某表某列的统计信息:
STAT 100 ON TABNAME(COLNAME);
注意:
以上DBMS_STATS包收集方式均可在最后添加参数DEGREE
:收集的并行度,默认为 1。以提高收集效率。DBMS_STATS包方法的具体使用手册可从数据库安装路径doc目录下《DM8系统包使用手册.pdf》查看。
另外
--收集表统计信息
call SP_TAB_STAT_INIT('OWNNAME','TABNAME');
--收集索引统计信息
call SP_INDEX_STAT_INIT('OWNNAME','INDNAME');
--生成表上所有索引的统计信息
call SP_TAB_INDEX_STAT_INIT ('OWNNAME', 'TABNAME');
注意:
- GATHER_TABLE_STATS 是用于收集和更新统计信息的操作,帮助查询优化器更好地优化查询执行计划。它支持并行度、采样、索引统计信息等选项,适用于数据量大的表和定期更新统计信息的场景。
- SP_TAB_STAT_INIT、SP_INDEX_STAT_INIT 是用于初始化或重置表的统计信息的存储过程,通常在表结构变化或数据量较少时使用。它会将统计信息重置为默认值,适用于需要重新收集统计信息的特殊场景。
三、查看统计信息
(1)查看单个表统计信息
DBMS_STATS.TABLE_STATS_SHOW('OWNNAME','TABNAME');
(2)批量查看某用户下表的统计信息
SELECT 'DBMS_STATS.TABLE_STATS_SHOW('''||OWNER||''','''||TABLE_NAME||''');' FROM DBA_TABLES WHERE OWNER = 'OWNNAME';
使用上述SQL执行后的结果集的SQL进行批量查询。
四、其他SQL
(1)查询表的最近一次收集统计信息的时间
SELECT
*
FROM
(SELECT
O.OBJECT_TYPE AS "对象类型",
O.OWNER AS "用户",
O.OBJECT_NAME AS "对象名称",
C.COLUMN_NAME AS "列名称",
C.COLUMN_ID AS "列ID",
C.DATA_TYPE AS "数据类型",
S.T_TOTAL AS "总行数",
S.N_SMAPLE AS "采样个数",
S.N_DISTINCT AS "不同值的个数",
S.N_NULL AS "空值个数",
S.V_MIN AS "列的最小值",
S.V_MAX AS "列的最大值",
S.N_BUCKETS AS "直方图桶数目",
S.LAST_GATHERED AS "最后收集时间"
FROM
SYSSTATS S
INNER JOIN DBA_OBJECTS O ON S.ID = O.OBJECT_ID
INNER JOIN DBA_TAB_COLUMNS C ON O.OWNER = C.OWNER AND O.OBJECT_NAME = C.TABLE_NAME AND S.COLID + 1 = C.COLUMN_ID
WHERE
O.OWNER = 'OWNNAME'
AND O.OBJECT_NAME = 'TABNAME'
AND O.OBJECT_TYPE = 'TABLE')
ORDER BY
C.COLUMN_ID;