本文于 113 天前发布,最后更新于 109 天前
一、前言
对象统计信息描述数据是如何在数据库中存储的。统计信息是优化器的代价计算的依据,可以帮助优化器较精确地估算成本,对执行计划的选择起着至关重要的作用。
达梦数据库的统计信息分三种类型:表统计信息、列统计信息、索引统计信息。通过直方图来表示。统计信息生成过程分以下三个步骤:
- 确定采样的数据:根据数据对象,确定需要分析哪些数据。
- 表:计算表的行数、所占的页数目、平均记录长度
- 列:统计列数据的分布情况
- 索引:统计索引列的数据分布情况
- 确定采样率
- 根据数据对象的大小,通过内部算法,确定数据的采样率。采样率与数据量成反比。
- 生成直方图
- 有两种类型的直方图:频率直方图和等高直方图。根据算法分析表的数据分布特征,确定直方图的类型。频率直方图的每个桶 (保存统计信息的对象) 的高度不同,等高直方图每个桶的高度相同。例如,对列生成统计信息,当列值分布比较均匀时,会采用等高直方图,否则,采用频率直方图。
在执行查询时,如果数据对象存在统计信息,代价算法可以根据统计信息中的数据,比较精确地计算出操作所需花费的成本,以此来确定连接方式、对象访问路径、连接顺序,选择最优的执行计划。
用户也可以通过修改 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 进行批量查询。
(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; |