Oracle里表、索引、列的统计信息

目录

一、表的统计信息

二、索引的统计信息

1、层级(level)

2、聚簇因子的含义及重要性

3、列的统计信息

3.1直方图(histogram)

1)直方图含义

2)直方图类型


一、表的统计信息

        表的统计信息用于描述表的详细信息,包括记录数(num_rows)、表块的数量(blocks)、平均行长度(avg_row_len)等典型维度。这些维度可以通过数据字典表*DBA_TABLES**DBA_TAB_PARTITIONS**DBA_TAB_SUBPARTITIONS*来分别查看表、分区表的分区和分区表的子分区的统计信息。

二、索引的统计信息

        索引的统计信息描述了索引的详细信息,它包含了索引的层级(blevel)、叶子块数量(leaf_blocks)、聚簇因子(clustering_factor)等典型维度。这些维度可以通过数据字典视图DBA_INDEXES、DBA_IND_PARTITIONS和DBA_IND_SUBPARTITIONS来分别查看索引、分区索引的分区、局部分区索引的子分区的统计信息。

1、层级(level)

        层级表示从根节点到叶子块的深度,层级被CBO用于计算访问索引叶子块的成本,层级越大,表示从根节点到叶子块所需要访问的数据块的数量就越多,耗费的i/o就会越多,索引访问的成本就会越大。在数据库里如果需要降低索引的层级,需要rebuild才可以。

2、聚簇因子的含义及重要性

        oracle数据库中,聚簇因子是指按照索引键值排序的索引行和存储于对应表中的数据行的存储顺序的相似程度。oracle数据库按照如下算法计算聚簇因子:

(1)聚簇因子初始值为1.

(2)oracle首先定位到目标索引处于最左边的叶子块。

(3)从最左边叶子块的第一个索引键值所在的索引行开始顺序扫描,在顺序扫描的过程中,        oracle会比较当前索引行的rowid和之前那个索引行的rowid,如果这两个rowid并不是指向同一个表块,那么oracle就将聚簇因子的当前值递增1;如果这两个rowid是指向同一个表块,oracle就不改变聚簇因子的值。oracle在比对rowid时并不会回表去访问相应的表块。

(4)上述的比对过程会持续下去,知道扫描完目标索引的所有索引块的所有索引行。

(5)上述顺序扫描完成后,聚簇因子的当前值就是索引统计信息中的clustering_factor,oracle将其存储在数据字典里。

        由以上的过程可知:聚簇因子高的索引走索引范围扫描时比相同条件下聚簇因子低的索引要耗费更多的物理i/o,所以聚簇因子高的索引走索引范围扫描的成本会比相同条件下聚簇因子低的索引走索引范围扫描的成本高。即聚簇因子越小越好。

        oracle数据库中,能够降低聚簇因子的唯一方法就是对表中数据按照目标索引的索引键值排序后重新存储。

        oracle数据库里,cbo在计算索引范围扫描(index range scan)的成本计算公式入下:

(*)IRS COST=I/O COST+CPU COST

(*)I/O COST=INDEX ACCESS I/O COST+TABLE ACCESS I/O COST

)index access i/o cost=blevel_celt(#leaf_blocksix_sel)

)table access i/o cost=celt(clustering_factorix_sel_with_filters)

        从这个公式可以推断出走索引范围扫描的成本可以近似看作是与聚簇因子成正比。因此,聚簇因子值得大小实际对CBO判断是否走相关索引起着至关重要的作用。

3、列的统计信息

        oracle里列的统计信息用于描述oracle数据库里列的详细信息,包括列的distinct值(num_distinct)、列的null值(num_nulls)得数量、列的最小值(low_value)、列的最大值(high_value)等一些典型维度。可以通过数据字典dba_tab_col_statistics、dba_part_col_statistics和dba_subpart_col_statistics分别查看表、分区表的分区、分区表的子分区的列的统计信息。

(1)列的distinct值(上述数据字典中字段num_distinct表示distinct值数量),cbo用num_distinct值来计算目标列做等值查询时的可选择率。

(2)上述字典中的字段num_nulls存储的就是目标列的null值数量,cbo用num_null值来评估对目标列施加“is null”或“is not null”条件后的返回结果集cardinality。另外cbo还用num_nulls值来调整对有null值得目标列做等值查询时的可选择率selectivity。

        对目标列进行等值查询时可选择率计算公式:selectivity=(1/num_distinct)*((num_rows-num_nulls)/num_rows)

(3)上述字典的列low_value和high_value值就是目标列的最小值和最大值,cbo通过low_value和high_value来计算目标列进行范围查询时可选择率selectivity的值。

        没有直方图,目标列范围查询可选择率计算公式(略)。

3.1直方图(histogram)

1)直方图含义

        在oracle数据库中,CBO会默认认为目标列的数据在最小值low_value和最大值high_value之间是均匀分布的,并且会根据这个均匀分布的原则来计算对目标列施加查询条件后的可选择率以及结果集的cardinality,进而据此来计算成本值并且选择执行计划。但是目标列的数据是均匀分布的这个原则并不总是准确的,在实际的系统中,我们很容易看到一些目标列的数据分布式不均匀的,甚至是极度倾斜的,分布极不均匀。对这样的列如果还按照均匀分布的原则去计算可选择率和结果集,并据此来计算成本,选择执行计划,那么CBO所选择的执行计划就可能是不合理的,甚至是错误的。

        对于上述问题,oracle引入了直方图。直方图是一种特殊的列的统计信息,它描述了目标列的数据分布情况。可以通过数据字典视图DBA_TAB_HISTOGRAMS、DBA_PART_HISTOGRAMS和DBA_SUBPART_HISTOGRAMS来分别查看表、分区表的分区和分区表的子分区的直方图统计信息。

        如果对目标列收集了直方图,则意味着CBO将不再认为该列上的数据是分布不均匀的,CBO就会用该目标列上的直方图统计信息来计算对该列施加查询条件后的可选择率和返回的结果集的cardinility,进而据此计算成本并选择相应的执行计划。即直方图就是oracle为了专门准确评估这种目标列分布不均匀的可选择率和结果集cardinility的方法。

2)直方图类型

        oracle数据库里的直方图使用了一种称为bucket的方式来描述目标列的数据分布。根据bucket的数量,直方图分为2类:

(1)frequency类型直方图:存储在数据字典里用于描述目标列直方图的bucket数量等于目标列的distinct数量。

        oracle直方图针对于文本类型的列收集直方图统计信息,则oracle只会将该文本字段头32位字符取出来,并将其转换成一个浮点数。然后将这个浮点数作为直方图统计信息存储在数据字典里。

(2)heigh balanced类型直方图:存储在数据字典里用于描述目标列直方图的bucket数量小于目标列的distinct数量。

  • 22
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
oracle动态性能 学习动态性能 第一篇--v$sysstat 2007.5.23   按照OracleDocument中的描述,v$sysstat存储自数据库实例运行那刻起就开始累计全实例(instance-wide)的资源使用情况。 类似于v$sesstat,该视图存储下统计信息: 1>.事件发生次数的统计(如:user commits) 2>.数据产生,存取或者操作的total(如:redo size) 3>.如果TIMED_STATISTICS值为true,则统计花费在执行操作上的总时间(如:CPU used by this session) v$sysstat视图常用介绍:  STATISTIC#: 标识  NAME: 统计项名称  VALUE: 资源使用量 该视图还有一class-统计类别但极少会被使用,各类信息如下: 1 代事例活动 2 代Redo buffer活动 4 代锁 8 代数据缓冲活动 16 代OS活动 32 代并行活动 64 代访问 128 代调试信息 注意:Statistic#的值在不同版本中各不相同,使用时要用Name做为查询条件而不要以statistic#的值做为条件。 使用v$sysstat中的数据   该视图中数据常被用于监控系统性能。如buffer cache命中率、软解析率等都可从该视图数据计算得出。   该视图中的数据也被用于监控系统资源使用情况,以及系统资源利用率的变化。正因如此多的性能数据,检查某区间内系统资源使用情况可以这样做,在一个时间段开始时创建一个视图数据快照,结束时再创建一个,二者之间各统计项值的不同(end value - begin value)即是这一时间段内的资源消耗情况。这是oracle工具的常用方法,诸如Statspack以及BSTAT/ESTAT都是如此。   为了对比某个区间段的数据,源数据可以被格式化(每次事务,每次执行,每秒钟或每次登陆),格式化后数据更容易从两者中鉴别出差异。这类的对比在升级前,升级后或仅仅想看看一段时间内用户数量增长或数据增加如何影响资源使用方面更加实用。   你也可以使用v$sysstat数据通过查询v$system_event视图来检查资源消耗和资源回收。 V$SYSSTAT中的常用统计   V$SYSSTAT中包含多个统计项,这部分介绍了一些关键的v$sysstat统计项,在调优方面相当有用。下按字母先后排序: 数据库使用状态的一些关键指标:  CPU used by this session:所有session的cpu占用量,不包括后台进程。这项统计的单位是百分之x秒.完全调用一次不超过10ms  db block changes:那部分造成SGA中数据块变化的insert,update或delete操作数 这项统计可以大概看出整体数据库状态。在各项事务级别,这项统计指出脏缓存比率。  execute count:执行的sql语句数量(包括递归sql)  logons current:当前连接到实例的Sessions。如果当前有两个快照则取平均值。  logons cumulative:自实例启动后的总登陆次数。  parse count (hard):在shared pool中解析调用的未命中次数。当sql语句执行并且该语句不在shared pool或虽然在shared pool但因为两者存在部分差异而不能被使用时产生硬解析。如果一条sql语句原文与当前存在的相同,但查询不同则认为它们是两条不同语句,则硬解析即会发生。硬解析会带来cpu和资源使用的高昂开销,因为它需要oracle在shared pool中重新分配内存,然后再确定执行计划,最终语句才会被执行。  parse count (total):解析调用总数,包括软解析和硬解析。当session执行了一条sql语句,该语句已经存在于shared pool并且可以被使用则产生软解析。当语句被使用(即共享) 所有数据相关的现有sql语句(如最优化的执行计划)必须同样适用于当前的声明。这两项统计可被用于计算软解析命中率。  parse time cpu:总cpu解析时间(单位:10ms)。包括硬解析和软解析。  parse time elapsed:完成解析调用的总时间花费。  physical reads:OS blocks read数。包括插入到SGA缓存区的物理读以及PGA中的直读这项统计并非i/o请求数。  physical writes:从SGA缓存区被DBWR写到磁盘的数据块以及PGA进程直写的数据块数量。  redo log space requests:在redo logs
一、重建索引的前提 1、上频繁发生update,delete操作; 2、上发生了alter table ..move操作(move操作导致了rowid变化)。 二、重建索引的标准 1、索引重建是否有必要,一般看索引是否倾斜的严重,是否浪费了空间, 那应该如何才可以判断索引是否倾斜的严重,是否浪费了空间, 对索引进行结构分析(如下): SQL>Analyze index index_name validate structure; 2、在执行步骤1的session中查询index_stats,不要到别的session去查询。 SQL>select height,DEL_LF_ROWS/LF_ROWS from index_stats; 说明:当 查询出来的 height>=4 或者 DEL_LF_ROWS/LF_ROWS>0.2 的场合 , 该索引考虑重建 。 举例: (t_gl_assistbalance 26 万多条信息 ) SQL> select count(*) from t_gl_assistbalance ; 输出结果: COUNT(*) ---------- 265788 SQL> Analyze index IX_GL_ASSTBAL_1 validate structure; Index analyzed SQL> select height,DEL_LF_ROWS/LF_ROWS from index_stats; 输出结果: HEIGHT DEL_LF_ROWS/LF_ROWS ---------- ------------------- 4 1 三、重建索引的方式 1、drop 原来的索引,然后再创建索引; 举例: 删除索引:drop index IX_PM_USERGROUP; 创建索引:create index IX_PM_USERGROUP on T_PM_USER (fgroupid); 说明:此方式耗时间,无法在24*7环境中实现,不建议使用。 2 、直接重建: 举例: alter index indexname rebuild; 或alter index indexname rebuild online; 说明:此方式比较快,可以在24*7环境中实现,建议使用此方式。 四、alter index rebuild 内部过程和注意点 alter index rebuild 和alter index rebuil online的区别 1、扫描方式不同 1.1、Rebuild以index fast full scan(or table full scan) 方式读取原索引中的数据来构建一个新的索引,有排序的操作; 1.2、rebuild online 执行扫描获取数据,有排序的操作; 说明:Rebuild 方式 (index fast full scan or table full scan 取决于统计信息的cost) 举例1 SQL> explain plan for alter index IX_GL_ASSTBAL_1 rebuild; Explained SQL> select * from table(dbms_xplan.display); PLAN_TABLE_OUTPUT --------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost | --------------------------------------------------------------------- | 0 | ALTER INDEX STATEMENT | | 999K| 4882K| 3219 | | 1 | INDEX BUILD NON UNIQUE| IDX_POLICY_ID2 | | | | | 2 | SORT CREATE INDEX | | 999K| 4882K| | | 3 | INDEX FAST FULL SCAN | IDX_POLICY_ID2 | 999K| 4882K| | --------------------------------------------------------------------- 举例2 SQL> explain plan for alter index idx_policy_id rebuild; Explained SQL> select * from table(dbms_xplan.display); PLAN_TABLE_OUTPUT --------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost | --------------------------------------------------------------------- | 0 | ALTER INDEX STATEMENT | | 2072K| 9M| 461 | | 1 | INDEX BUILD NON UNIQUE| IDX_POLICY_ID | | | | | 2 | SORT CREATE INDEX | | 2072K| 9M| | | 3 | TABLE ACCESS FULL | TEST_INDEX | 2072K| 9M| 461 | 举例3 ( 注意和 举例1 比较 ) Rebuil online 方式 : SQL> explain plan for alter index idx_policy_id2 rebuild online; Explained SQL> select * from table(dbms_xplan.display); PLAN_TABLE_OUTPUT --------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost | ---------------------------------------------------------------------| 0 | ALTER INDEX STATEMENT | | 999K| 4882K| 3219 | | 1 | INDEX BUILD NON UNIQUE| IDX_POLICY_ID2 | | | | | 2 | SORT CREATE INDEX | | 999K| 4882K| | | 3 | TABLE ACCESS FULL | TEST_INDEX2 | 999K| 4882K| 3219 | 2 、rebuild 会阻塞 dml 操作 ,rebuild online 不会阻塞 dml 操作 ; 3 、rebuild online 时系统会产生一个 SYS_JOURNAL_xxx 的 IOT 类型的系统临时日志 , 所有 rebuild online 时索引的变化都记录在这个中 , 当新的索引创建完成后 , 把这个的记录维护到新的索引中去 , 然后 drop 掉旧的索引 ,rebuild online 就完成了。 注意点: 1、 执行rebuild操作时,需要检查空间是否足够; 2、虽然说rebuild online操作允许dml操作,但是还是建议在业务不繁忙时间段进行; Rebuild操作会产生大量redo log ; 五、重建分区上的分区索引 重建分区索引方法: Alter index indexname rebuild partition paritionname tablespace tablespacename; Alter index indexname rebuild subpartition partitioname tablespace tablespacename; Partition name 可以从user_ind_partitions查找 Tablepace 参数允许alter index操作更改索引的存储空间; 六、索引状态描述 在数据字典中查看索引状态,发现有三种: valid:当前索引有效 N/A :分区索引 有效 unusable:索引失效 七、术语 1、高基数:简单理解就是的不同值多。 2、低基数:建单理解就是中的的不同值少。 3、以删除的叶节点数量:指得是数据行的delete操作从逻辑上删除的索引节点 的数量,要记住oracle在删除数据行后,将 “ 死 “ 节点保留在索引中,这样做可以加快sql删除操作的速度,因此oracle删除数据行后可以不必重新平衡索引。 4、索引高度:索引高度是指由于数据行的插入操作而产生的索引层数,当中添加大量数据时,oracle将生成索引的新层次以适应加入的数据行,因此,oracle索引可能有4层,但是这只会出现在索引数中产生大量插入操作的区域。Oracle索引的三层结构可以支持数百万的项目,而具备4层或是更多层的需要重建。 5、每次索引访问的读取数:是指利用索引读取一数据行时所需要的逻辑I/O操作数,逻辑读取不必是物理读取,因为索引的许多内容已经保存在数据缓冲区,然而,任何数据大于10的索引都需要重建。 6、什么时候重建呢? 察看 dba_indexes 中的 blevel 。这是说明索引从根块到叶快的级别,或是深度。如果级别大于等于4。则需要重建, 如下 :Select index_name,blevel from dba_indexes where blevel>=4. 另一个从重建中受益的指标显然是当该索引中的被删除项占总的项数的百分比。如果在20%以上时,也应当重建,如下 SQL>analyze index index_name validate structure SQL>select (del_lf_rows_len/lf_rows_len)*100 from index_stats where name= ’ index_name ’ 就能看到是否这个索引被删除的百分比。 7、什么样的重建方式更好? (1)、建索引的办法: 1.1、删除并从头开始建立索引。 1.2 、 使用 alter index index_name rebuild 命令重建索引。 1.3 、 使用 alter index index_name coalesce 命令重建索引。 (2)、下面讨论一下这三种方法的优缺点: 2.1、删除并从头开始建索引:方法是最慢的,最耗时的。一般不建议。 2.2、Alter index index_name rebuild 快速重建索引的一种有效的办法,因为使用现有索引项来重建新索引,如果客户操作时有其他用户在对这个操作,尽量使用带online参数来最大限度的减少索引重建时将会出现的任何加锁问题,alter index index_name rebuild online。 但是,由于新旧索引在建立时同时存在,因此,使用这种技巧则需要有额外的磁盘空间可临时使用,当索引建完后把老索引删除,如果没有成功,也不会影响原来的索引。利用这种办法可以用来将一个索引移到新的空间。 Alter index index_name rebuild tablespace tablespace_name 。 这个命令的执行步骤如下: 首先,逐一读取现有索引,以获取索引的关键字。 其次,按新的结构填写临时数据段。 最后,一旦操作成功,删除原有索引树,降临时数据段重命名为新的索引。 需要注意的是alter index index_name rebuild 命令中必须使用tablespace字句,以保证重建工作是在现有索引相同的空间进行。 2.3、alter index index_name coalesce 使用带有coalesce参数时重建期间不需要额外空间,它只是在重建索引时将处于同一个索引分支内的叶块拼合起来,这最大限度的减少了与查询过程中相关的潜在的加锁问题,但是,coalesce选项不能用来将一个索引转移到其他空间。 八、其他 1、truncate 分区操作和truncate 普通的区别? 1.1、Truncate 分区操作会导致全局索引失效; truncate 普通索引没有影响; 1.2、Truncate 分区操作不会释放全局索引中的空间,而truncate 普通会释放索引所占空间; 2、rename 名操作对索引没有影响,因为rename操作只是更改了数据字典,中数据行的rowid并没有发生变化 总结: 1、判断是否需要重建索引: SQL>analyze index index_name validate structure; SQL> select height,DEL_LF_ROWS/LF_ROWS from index_stats; ( 或 Select index_name,blevel from dba_indexes where blevel>=4 ); 说明 : 当查询出来的 height>=4 或者 DEL_LF_ROWS/LF_ROWS>0.2 的场合 , 该索引考虑重建 ; 2 、重建索引方法 : 方法一、 Alter index index_name rebuild tablespace tablespace_name; 优点:是快速重建索引的一种有效的办法,可以用来将一个索引移到新的空间。 缺点:重建期间需要额外空间。 方法二、 alter index index_name coalesce; 优点:重建期间不需要额外空间。 缺点:coalesce选项不能用来将一个索引转移到其他空间。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GawynKing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值