Oracle索引碎片检查及定期重建常用表的索引
背景说明:
今天查阅书籍时,偶然间发现“在对某个索引行执行删除操作时,只是为该行增加了一个删除标记,这个索引行并不会释放它的存储空间,Insert产生的新的索引行也不能被插入到该位置。索引列的修改过程其实是将对应的列值删除,然后再插入新的列值(与数据行本身的修改是不一致的,这也正是我们尽量不使用修改频繁的列来创建索引的原因)。所以,无论是插入、修改、删除,都需要消耗存储空间,增大B-Tree索引结构的深度,影响数据的查询速度。尤其是删除和修改,不仅造成了存储空间的浪费,而且增加了扫描索引块的数量”,这就是所谓的索引碎片问题,建议定期对经常使用的表执行检查和重建索引操作。
问题重现:
经测试,收集统计信息等操作,无法释放索引删除块所占用的存储空间。
analyze table tkk29 compute statistics;
select t.index_name, t.distinct_keys, t.num_rows, t.sample_size, t.last_analyzed
, t.blevel, t.leaf_blocks, t.*
from user_indexes t
where t.table_name = upper('tkk29');

delete from tkk29
where mod(trunc((sysdate-createddate) * 24 * 60), 2) = 0;
analyze table tkk29 compute statistics;
analyze index IDX_tkk29_PARTICIPANT validate structure;
select t.name, t.blocks, t.lf_rows, t.del_lf_rows, t.lf_rows - t.del_lf_rows as lf_rows_used
, to_char((t.del_lf_rows/t.lf_rows) * 100, '999.999') as ratio, t.*
from index_stats t


alter index IDX_tkk29_PARTICIPANT rebuild;
alter index IDX_tkk29_ACTUALPARTICIPANT rebuild;
analyze index IDX_tkk29_PARTICIPANT validate structure;


重建索引:
CREATE OR REPLACE TYPE strsplit_type AS TABLE OF VARCHAR2(32676); CREATE OR REPLACE FUNCTION strsplit(p_value VARCHAR2, p_split VARCHAR2 := ',')
--usage: select * from table(strsplit('1,2,3,4,5'))
RETURN strsplit_type
PIPELINED IS
v_idx INTEGER;
v_str VARCHAR2(500);
v_strs_last VARCHAR2(4000) := p_value;
BEGIN
LOOP
v_idx := instr(v_strs_last, p_split);
EXIT WHEN v_idx = 0;
v_str := substr(v_strs_last, 1, v_idx - 1);
v_strs_last := substr(v_strs_last, v_idx + 1);
PIPE ROW(v_str);
END LOOP;
PIPE ROW(v_strs_last);
RETURN;
END strsplit;
CREATE OR REPLACE PROCEDURE UP_CHECK_TO_REBUILD_INDEX
(
tbNames varchar
)
IS
sqlstr VARCHAR2(100);
idx_ratio INT;
BEGIN
--DECLARE sqlstr VARCHAR2(100);
-- idx_ratio INT;
BEGIN
FOR idx IN (SELECT t.index_name FROM user_indexes t
WHERE t.index_type = 'NORMAL' AND t.status = 'VALID' AND t.temporary = 'N' AND t.leaf_blocks > 100
AND t.table_name IN (SELECT UPPER(TRIM(COLUMN_VALUE)) from table(strsplit(tbNames))) --//('TKK29')
ORDER BY t.table_name, t.index_name
)
LOOP
DBMS_OUTPUT.put_LINE(idx.index_name || ' ANALYZE START ' || TO_CHAR(SYSDATE, 'yyyy-MM-dd hh24:mi:ss'));
sqlstr := 'ANALYZE INDEX ' || idx.Index_Name || ' VALIDATE STRUCTURE';
EXECUTE IMMEDIATE sqlstr; SELECT TRUNC((t.del_lf_rows/t.lf_rows) * 100) INTO idx_ratio
FROM index_stats t WHERE t.name=idx.index_name AND ROWNUM=1; IF (idx_ratio >= 15) THEN
DBMS_OUTPUT.put_line(' REINDEX ' || TO_CHAR(SYSDATE, 'yyyy-MM-dd hh24:mi:ss') || ' ratio: ' || idx_ratio);
sqlstr := 'ALTER INDEX ' || idx.index_name || ' REBUILD';
EXECUTE IMMEDIATE sqlstr;
END IF;
END LOOP;
END;
END UP_CHECK_TO_REBUILD_INDEX; SQL>exec UP_CHECK_TO_REBUILD_INDEX('TKK29, muser'); begin
UP_CHECK_TO_REBUILD_INDEX('TKK29, muser');
end;
PK_MUSER ANALYZE START 2016-01-29 17:49:19
IDX_TKK29_ACTIVITYINSTANCEID ANALYZE START 2016-01-29 17:49:19
REBUILD INDEX START 2016-01-29 17:49:20 ratio: 50
IDX_TKK29_ACTUALPARTICIPANT ANALYZE START 2016-01-29 17:49:22
IDX_TKK29_COMPLETEDDATE ANALYZE START 2016-01-29 17:49:22
REBUILD INDEX START 2016-01-29 17:49:22 ratio: 36
IDX_TKK29_PARTICIPANT ANALYZE START 2016-01-29 17:49:23
IDX_TKK29_PROCESSINSTANCEID ANALYZE START 2016-01-29 17:49:23
REBUILD INDEX START 2016-01-29 17:49:24 ratio: 50
IDX_TKK29_STATEDDATE ANALYZE START 2016-01-29 17:49:25
REBUILD INDEX START 2016-01-29 17:49:25 ratio: 33
PK_TKK29 ANALYZE START 2016-01-29 17:49:27
REBUILD INDEX START 2016-01-29 17:49:27 ratio: 50
备注:
真实场景请考虑索引列的修改、数据删除的概率,结合表的数据量大小等多种因素制定合理的维护计划;另外,分区表的不同分区应该有不同的策略。
Oracle索引碎片检查及定期重建常用表的索引的更多相关文章
- oracle删除当前用户以及当前用户所有表、索引等操作
ORACLE删除当前用户下所有的表的方法 如果有删除用户的权限,则可以: drop user user_name cascade; 加了cascade就可以把用户连带的数据全部删掉.删除后再创建该用户 ...
- ORACLE关于索引是否需要定期重建争论的整理
ORACLE数据库中的索引到底要不要定期重建呢? 如果不需要定期重建,那么理由是什么? 如果需要定期重建,那么理由又是什么?另外,如果需要定期重建,那么满足那些条件的索引才需要重建呢?关于这个问题,网 ...
- Oracle查询索引碎片及数据表空间使用情况
--检查索引碎片情况,只能对单个表进行分析. --需要注意块的大小.索引的pctfree的值的大小.rowid的长度的不同,根据不同的情况修改相应的值 select index_name, c.NMB ...
- Oracle索引以及索引碎片
索引,可以增加查询速度,若没有索引,每次查询都必须是全表查询.例如,搜索某个记录时(如name="gdpuzxs")时,需要全表扫描一下,因为不知道有多少个name="g ...
- SQLServer中重建聚集索引之后会影响到非聚集索引的索引碎片吗
本文出处:http://www.cnblogs.com/wy123/p/7650215.html (保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错 ...
- SQL Server 索引碎片产生原理重建索引和重新组织索引
数据库存储本身是无序的,建立了聚集索引,会按照聚集索引物理顺序存入硬盘.既键值的逻辑顺序决定了表中相应行的物理顺序 多数情况下,数据库读取频率远高于写入频率,索引的存在 为了读取速度牺牲写入速度 页 ...
- [笔记整理]SQL Server 索引碎片 和 重建索引
铺垫知识点: 数据库存储本身是无序的,建立了聚集索引,会按照聚集索引物理顺序存入硬盘.既键值的逻辑顺序决定了表中相应行的物理顺序 多数情况下,数据库读取频率远高于写入频率,索引的存在 为了读取速度牺牲 ...
- 转: SQL Server索引的维护 - 索引碎片、填充因子
转:http://www.cnblogs.com/kissdodog/archive/2013/06/14/3135412.html 实际上,索引的维护主要包括以下两个方面: 页拆分 碎片 这两个问题 ...
- SQL Server索引的维护 - 索引碎片、填充因子 <第三篇>
实际上,索引的维护主要包括以下两个方面: 页拆分 碎片 这两个问题都和页密度有关,虽然两者的表现形式在本质上有所区别,但是故障排除工具是一样的,因为处理是相同的. 对于非常小的表(比64KB小得多), ...
随机推荐
- em 和 px相互转换
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- IOS百度地图获取所在的城市名称
笔者的app要实现定位所在省和城市名称,借此总结巩固一下! @interface VenueListVC : BasePageTableViewVC<BMKLocationServiceDele ...
- word常用操作
[Word2003文档添加个行号] 参考:http://jingyan.baidu.com/article/e9fb46e1ca1d3c7520f7666f.html#333225-tsina-1-5 ...
- c++类的嵌套(1)
在一个类的内部定义另一个类或结构体,我们称之为嵌套类(nested class),或者嵌套类型.之所以引入这样一个嵌套类,往往是因为外围类需要使用嵌套类对象作为底层实现,并且该嵌套类只用于外围类的实现 ...
- 第七周——Linux内核如何装载和启动一个可执行程序
万子惠 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 part1 实验 ...
- java生成二维码(需导入第三方ZXing.jar包)
//这个类是用来解析,通过图片解析该图片的网页链接是什么 package util; import java.awt.Graphics2D;import java.awt.geom.AffineTra ...
- java文件编译及运行
1 配置环境变量 使用鼠标右击“我的电脑”->属性->高级->环境变量 系统变量->新建->变量名:JAVA_HOME 变量值:C:\Program Files (x86 ...
- js 控制框架页面跳转 top.location.herf = "url"
top.location.href和localtion.href有什么不同 top.location.href=”url” 在顶层页面打开url(跳出框架) self.locatio ...
- [读书笔记]java中的volatile关键词
以下内容大多来自周志明的<深入理解Java虚拟机>. 当一个变量被volatile修饰后,它将具备两种特性: 1. 保证此变量对所有线程的可见性,这里的“可见性”是指当一条线程修改了这个变 ...
- 当padding,margin,top为百分比值,具体数值如何计算
padding以及margin的四个方向设置值为百分数的时候,是以父元素的宽度为基数来进行计算. (为了保持横向和纵向方向上的margin/padding一致,但是其实也不是一定以父元素的宽度为参照物 ...