Oracle索引梳理系列(九)- 浅谈聚簇因子对索引使用的影响及优化方法
版权声明:本文发布于http://www.cnblogs.com/yumiko/,版权由Yumiko_sunny所有,欢迎转载。转载时,请在文章明显位置注明原文链接。若在未经作者同意的情况下,将本文内容用于商业用途,将保留追究其法律责任的权利。如果有问题,请以邮箱方式联系作者(793113046@qq.com)。
1、聚簇因子的概念
- 聚簇因子,是CBO优化器决定是否使用索引的因素之一,主要反映索引块上的数据(顺序存储),与该索引基于的表块上的数据(无序存储)的顺序相似程度的差异性。即表数据的存储顺序是否与相应索引数据的存储顺序一致。
- 通过查询dba_indexes视图、user_indexes视图以及all_indexes视图的CLUSTERING_FACTOR列,可以了解当前索引的聚簇因子值。
2、索引块与相应数据块之间数据分布产生差异的原因
对于索引块的数据存储,这里以普通btree索引为例,索引块中键值的分布总是有序的,且根据键值及其相应的rowid信息,唯一定位一行记录在相应表的数据块中的分布。理想情况下,相同或相邻的键值,尽量定位在相同的数据块上,可以避免对于数据块多余的I/O操作。
- 对于数据块的数据存储,并不是有序存储的。且ORACLE为节省空间,会优先使用当前当水位线(HWM)以下的可用数据块,而不是按序使用最后被使用的块。当HWM以下无可用数据块时,再开辟新的数据块使用。
- 正因为数据块中数据存储的特点,随着时间的推移,数据在相应数据块间的分布越发零散,进而影响索引块中,相同或相邻键值对应的相应数据行信息(rowid),所指向的数据块越加分散,进而导致聚簇因子变差。
3、聚簇因子的计算方法
聚簇因子大致的计算方法顺序如下:
- 进行一次索引全扫描
- 检查索引块中的rowid信息。比较前一个rowid与一个rowid是否指向同一个数据块。若不同,则聚簇因子加1.
- 当完成整个的索引扫面后,即得到该索引的聚簇因子的数值。
4、聚簇因子好坏的判断
良好的CF值,会趋向于数据表的块数。
较差的CF值,会趋向于数据表的行数。
需要注意的是:随着时间的推移,频繁的DML操作,会让CF值总是趋向于恶劣方向发展。
示例:
本示例主要说明CF的趋势性。
--查看当前测试表中索引的聚簇因子情况
--注意此时的LAST_ANALYZED为空,说明未收集过统计信息
Yumiko_sunny@OA01> select INDEX_NAME,b.TABLE_NAME,CLUSTERING_FACTOR,
2 a.BLOCKS tb_blocks,b.NUM_ROWS tb_rows,
3 to_char(c.LAST_ANALYZED,'YYYY-MM-DD HH24:MI:SS') LAST_ANALYZED
4 from dba_segments a,dba_indexes b ,dba_tables c
5 where a.segment_name=b.table_name
6 and a.segment_name=c.table_name
7 and b.table_name='TEST'; INDEX_NAME TABLE_NAME CLUSTERING_FACTOR TB_BLOCKS TB_ROWS LAST_ANALYZED
--------------- --------------- ----------------- ---------- ---------- -------------------
TEST_IDX TEST 17381 18432 1217342 --分析收集表test最新的统计信息
Yumiko_sunny@OA01> analyze table test compute statistics;
Table analyzed. --查看收集后最新的信息,可以看到,结果集中CF值,明显小于数据块值,说明此时情况相似度很好。
Yumiko_sunny@OA01> select INDEX_NAME,b.TABLE_NAME,CLUSTERING_FACTOR,
2 a.BLOCKS tb_blocks,b.NUM_ROWS tb_rows,
3 to_char(c.LAST_ANALYZED,'YYYY-MM-DD HH24:MI:SS') LAST_ANALYZED
4 from dba_segments a,dba_indexes b ,dba_tables c
5 where a.segment_name=b.table_name
6 and a.segment_name=c.table_name
7 and b.table_name='TEST'; INDEX_NAME TABLE_NAME CLUSTERING_FACTOR TB_BLOCKS TB_ROWS LAST_ANALYZED
--------------- --------------- ----------------- ---------- ---------- -------------------
TEST_IDX TEST 17381 18432 1217342 2016-11-06 16:38:08 --插入新的数据并进行提交
Yumiko_sunny@OA01> insert into test select * from test;
1217342 rows created. Yumiko_sunny@OA01> commit;
Commit complete. --再次收集表test相关的统计信息
Yumiko_sunny@OA01> analyze table test compute statistics;
Table analyzed. --不难发现,随着insert的操作,CF值发生了改变,虽然目前该值在可接受范围内,但已经开始趋向行数。
--可以想象下,一个生产环境中,除了insert,还有update跟delete,随着这些操作的增多,势必更加趋向行数。
Yumiko_sunny@OA01> select INDEX_NAME,b.TABLE_NAME,CLUSTERING_FACTOR,
2 a.BLOCKS tb_blocks,b.NUM_ROWS tb_rows,
3 to_char(c.LAST_ANALYZED,'YYYY-MM-DD HH24:MI:SS') LAST_ANALYZED
4 from dba_segments a,dba_indexes b ,dba_tables c
5 where a.segment_name=b.table_name
6 and a.segment_name=c.table_name
7 and b.table_name='TEST'; INDEX_NAME TABLE_NAME CLUSTERING_FACTOR TB_BLOCKS TB_ROWS LAST_ANALYZED
--------------- --------------- ----------------- ---------- ---------- -------------------
TEST_IDX TEST 206123 35840 2016-11-06 16:39:58
5、聚簇因子的优化
由于影响CF(CLUSTERING_FACTOR)值的主要取决于数据表的数据,在数据块中的存储分布情况,因此优化CF的重点还是在调整数据表本身,具体方法如下:
- 定期按索引列顺序重建表
- 建议通过dbms_metadata.get_ddl提取表结构完整的DDL语句,结合insert order by column以及rename table的方式进行表的重建。
- 不建议采用CTAS方式(create table as select),该方式可能引起后续不必要的麻烦。具体影响可参阅链接中的案例 http://blog.csdn.net/leshami/article/details/7362156
- 使用聚簇表代替普通的数据表
- 频繁DML的表以及经常需要全表扫描的表,不适合建立聚簇表。
- 具体查阅作者前面关于“表簇索引”一文的介绍 “Oracle索引种类之表簇索引(cluster index)”
示例:
本示例承接上面的示例,主要演示通过重建表的方式进行聚簇因子优化的过程。
--再次确认原始表test的CF值
Yumiko_sunny@OA01> select INDEX_NAME,b.TABLE_NAME,CLUSTERING_FACTOR,
2 a.BLOCKS tb_blocks,b.NUM_ROWS tb_rows,
3 to_char(c.LAST_ANALYZED,'YYYY-MM-DD HH24:MI:SS') LAST_ANALYZED
4 from dba_segments a,dba_indexes b ,dba_tables c
5 where a.segment_name=b.table_name
6 and a.segment_name=c.table_name
7 and b.table_name='TEST'; INDEX_NAME TABLE_NAME CLUSTERING_FACTOR TB_BLOCKS TB_ROWS LAST_ANALYZED
--------------- --------------- ----------------- ---------- ---------- -------------------
TEST_IDX TEST 35840 2434684 2016-11-06 22:10:51 --通过调用dbms_metadata包的get_ddl函数,抽取原始表test的DDL结构语句
Yumiko_sunny@OA01> set long 100000
Yumiko_sunny@OA01> set pages 0
Yumiko_sunny@OA01> select dbms_metadata.get_ddl('TABLE',upper('&table_name'),upper('&owner')) from dual;
Enter value for table_name: TEST
Enter value for owner: SCOTT
old 1: select dbms_metadata.get_ddl('TABLE',upper('&table_name'),upper('&owner')) from dual
new 1: select dbms_metadata.get_ddl('TABLE',upper('TEST'),upper('SCOTT')) from dual CREATE TABLE "SCOTT"."TEST"
( "OWNER" VARCHAR2(30),
"OBJECT_NAME" VARCHAR2(128),
"SUBOBJECT_NAME" VARCHAR2(30),
"OBJECT_ID" NUMBER,
"DATA_OBJECT_ID" NUMBER,
"OBJECT_TYPE" VARCHAR2(19),
"CREATED" DATE,
"LAST_DDL_TIME" DATE,
"TIMESTAMP" VARCHAR2(19),
"STATUS" VARCHAR2(7),
"TEMPORARY" VARCHAR2(1),
"GENERATED" VARCHAR2(1),
"SECONDARY" VARCHAR2(1),
"NAMESPACE" NUMBER,
"EDITION_NAME" VARCHAR2(30)
) SEGMENT CREATION IMMEDIATE
PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255
NOCOMPRESS LOGGING
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "USERS" --利用抽取的原始表test的结构语句,创建新表test_tmp
Yumiko_sunny@OA01> CREATE TABLE "SCOTT"."TEST_TMP"
2 ( "OWNER" VARCHAR2(30),
3 "OBJECT_NAME" VARCHAR2(128),
4 "SUBOBJECT_NAME" VARCHAR2(30),
5 "OBJECT_ID" NUMBER,
6 "DATA_OBJECT_ID" NUMBER,
7 "OBJECT_TYPE" VARCHAR2(19),
8 "CREATED" DATE,
9 "LAST_DDL_TIME" DATE,
10 "TIMESTAMP" VARCHAR2(19),
11 "STATUS" VARCHAR2(7),
12 "TEMPORARY" VARCHAR2(1),
13 "GENERATED" VARCHAR2(1),
14 "SECONDARY" VARCHAR2(1),
15 "NAMESPACE" NUMBER,
16 "EDITION_NAME" VARCHAR2(30)
17 ) SEGMENT CREATION IMMEDIATE
18 PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255
19 NOCOMPRESS LOGGING
20 STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
21 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
22 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
23 TABLESPACE "USERS"; Table created. --通过对原始表test的索引列进行order by排序操作后,差入到新表test_tmp中
--通过append hint的方法,虽然可以减少redo的产生,并且在hwm以上开辟数据块,加快了数据的加载速度。
--但该方式,在commit或者rollback事物前,其他会话无法针对该表进行DML操作,生产环境中需要注意。
Yumiko_sunny@OA01> insert into /*+append */ test_tmp select * from test order by object_id;
2434684 rows created. Yumiko_sunny@OA01> commit; --为新表test_tmp的索引列添加索引
Yumiko_sunny@OA01> create index test_idx_new on test_tmp(object_id);
Index created. --将原始表test进行重命名test_old
Yumiko_sunny@OA01> alter table test rename to test_old;
Table altered. --将新表test_tmp重命名为test
Yumiko_sunny@OA01> alter table test_tmp rename to test;
Table altered. --分析收集新表test的统计信息
Yumiko_sunny@OA01> analyze table TEST compute statistics;
Table analyzed. --查看新建的表test的CF,不难发现,此时的CF值将较之前已经明显下降。
--至此,CF的优化过程结束。
Yumiko_sunny@OA01> select INDEX_NAME,b.TABLE_NAME,CLUSTERING_FACTOR,
2 a.BLOCKS tb_blocks,b.NUM_ROWS tb_rows,
3 to_char(c.LAST_ANALYZED,'YYYY-MM-DD HH24:MI:SS') LAST_ANALYZED
4 from dba_segments a,dba_indexes b ,dba_tables c
5 where a.segment_name=b.table_name
6 and a.segment_name=c.table_name
7 and b.table_name='TEST'; INDEX_NAME TABLE_NAME CLUSTERING_FACTOR TB_BLOCKS TB_ROWS LAST_ANALYZED
----------------------------------------------------------------------------------------
TEST_IDX_NEW TEST 39700 35840 2434684 2016-11-06 22:26:10
需要补充说明的是:
对于alter table move的操作,可以降低高水位线,但对于优化聚簇因子值而言,意义不大。
对于重建索引,通过实验发现(只进行了两个实验,可能结果集存在误差),聚簇因子值不但未降低,有时还存在些许的增加,需要注意。
Oracle索引梳理系列(九)- 浅谈聚簇因子对索引使用的影响及优化方法的更多相关文章
- [独孤九剑]Oracle知识点梳理(九)数据库常用对象之package
本系列链接导航: [独孤九剑]Oracle知识点梳理(一)表空间.用户 [独孤九剑]Oracle知识点梳理(二)数据库的连接 [独孤九剑]Oracle知识点梳理(三)导入.导出 [独孤九剑]Oracl ...
- 【公众号系列】浅谈SAP项目管理的技能
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[[公众号系列]浅谈SAP项目管理的技能 写 ...
- 【ASP.NET MVC系列】浅谈数据注解和验证
[ASP.NET MVC系列]浅谈数据注解和验证 [01]浅谈Google Chrome浏览器(理论篇) [02]浅谈Google Chrome浏览器(操作篇)(上) [03]浅谈Google C ...
- 【Fiori系列】浅谈SAP Fiori的设计美感与发展历程
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[Fiori系列]浅谈SAP Fiori的设计美 ...
- Spring5.0源码学习系列之浅谈BeanFactory创建
Spring5.0源码学习系列之浅谈BeanFactory创建过程 系列文章目录 提示:Spring源码学习专栏链接 @ 目录 系列文章目录 博客前言介绍 一.获取BeanFactory主流程 二.r ...
- 浅谈分词算法(5)基于字的分词方法(bi-LSTM)
目录 前言 目录 循环神经网络 基于LSTM的分词 Embedding 数据预处理 模型 如何添加用户词典 前言 很早便规划的浅谈分词算法,总共分为了五个部分,想聊聊自己在各种场景中使用到的分词方法做 ...
- 浅谈分词算法(4)基于字的分词方法(CRF)
目录 前言 目录 条件随机场(conditional random field CRF) 核心点 线性链条件随机场 简化形式 CRF分词 CRF VS HMM 代码实现 训练代码 实验结果 参考文献 ...
- 浅谈分词算法(3)基于字的分词方法(HMM)
目录 前言 目录 隐马尔可夫模型(Hidden Markov Model,HMM) HMM分词 两个假设 Viterbi算法 代码实现 实现效果 完整代码 参考文献 前言 在浅谈分词算法(1)分词中的 ...
- Oracle索引梳理系列(五)- Oracle索引种类之表簇索引(cluster index)
版权声明:本文发布于http://www.cnblogs.com/yumiko/,版权由Yumiko_sunny所有,欢迎转载.转载时,请在文章明显位置注明原文链接.若在未经作者同意的情况下,将本文内 ...
随机推荐
- ubuntu 启动MySql和安装python的MySQLdb模块
ubuntu一般会自己预安装mysql,你只需 /etc/init.d/mysql start|stop|restart|reload|force-reload|status 命令便可以实现mysq ...
- Objective-C 生成器模式 -- 简单实用和说明
1.生成器模式的定义 将一个复杂的对象的构件与它的表示分离,使得同样的构建过程可以创建不同的表示 2.生成器模式的UML Builder :生成器接口,定义创建一个Product各个部件的操作 Con ...
- NLog在Asp.Net MVC的实战应用
Asp.Net MVC FilterAttribute特性.读取xml反序列化.NLog实战系列文章 首先新建一个MVC project. 一.NLog的配置. 作者:Jarosław Kowalsk ...
- iOS集成sharesdk遇到的坑
分享新浪微博 ★★★分享新浪微博★★★ 前言: 写这个目地是为了记录那些过坑,直接先上效果图.大家看看如果你遇到了应该如果处理更好,因为刚一看到这个效果的时候就明白其实很简单不就是分享微博吧.但是要求 ...
- Nginx服务器之Nginx与tomcat结合访问jsp
本文使用linux centos系统 本文概述: JSP是一种动态网页技术标准.使用的方式是在HTML文件中插入程序段和JSP标记,而形成JSP文件.使用JSP开发WEB应用可以跨平台开发.但jsp需 ...
- Android笔记——AsyncTask介绍
AsyncTask和Handler对比 1 ) AsyncTask实现的原理,和适用的优缺点 AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操 ...
- Web API与OAuth:既生access token,何生refresh token
在前一篇博文中,我们基于 ASP.NET Web API 与 OWIN OAuth 以 Resource Owner Password Credentials Grant 的授权方式( grant_t ...
- 读书笔记--SQL必知必会07--创建计算字段
7.1 计算字段 字段(field),基本与列(column)含义相同. 利用计算字段可以直接从数据库中检索出转换.计算或格式化过的数据. 计算字段不实际存在于数据库表中,是运行时在SELECT语句内 ...
- Js ==和===的区别
===判断: Undefined === Undefined,返回 true Null === Null,返回 true null == undefined,返回 false NaN === NaN, ...
- centos7查看系统版本,查看机器位数x86-64
前言 由于不经常使用linux,每当使用的时候就是安装软件,安装软件的时候就要选择安装包平台,是32位的还是64位的.这时候突然发现不知道怎么查,于是百度.虽然轻而易举百度出来,但仍旧没有自己的笔记看 ...