2、重建索引

重建索引在常规的数据库维护操作中经常使用。在数据库运行了较长时间后,索引都有损坏的可能,这时就需要重建。对数据重建索引可以起到提高检索效率。

mysql> REPAIR TABLE `table_name` QUICK;

什么时候需要重建索引

索引在普遍意义上能够给数据库带来带来提升,但索引的额外开销也是不容小视的,而索引的重建也是维护索引的重要工作之一。

经过维护的索引可带来以下好处:

1、CBO对于索引的使用可能会产生一个较小的成本值,从而在执行计划中选择使用索引。

2、使用索引扫描的查询扫描的物理索引块会减少,从而提高效率。

3、于需要缓存的索引块减少了,从而让出了内存以供其他组件使用。

重建索引的原因主要包括:

1、

删除的空间没有重用,导致

索引出现碎片

2、

删除大量的表数据后,空间没有重用,导致

索引"虚高"

3、索引的

clustering_facto

和表不一致

也有人认为当索引树高度超过4的时候需要进行重建,但是如果表数量级较大,自然就不会有较高的树,而且重建不会改变索引树高度,除非是由于大量引起的索引树“虚高”,重建才会改善性能,当然这又回到了索引碎片的问题上了。

索引出现碎片

由于索引中只有删除和插入操作,且索引中更新完全不同于表达更新。如果索引中的

记录关键字需要更新,就需要将旧记录的位置标记为删除,并在相应的叶子节点插入新的索引纪录。这种删除标记并非真正的删除索引块中的记录,索引块中被标记

为删除的记录只有在相同索引条目插入到相同块的相同位置时才能重用。由于即使相同的索引记录也不一定插入到被删除的空间中,故如果对索引频繁进行

update和delete操作很容易导致索引出现碎片。较高的PCTFREE也容易出现索引碎片。索引的碎片也就导致了,访问索引数据时需要访问更多的

索引块

索引虚高

上面的说的是频繁update和delete导致索引块中有碎片,那如果进行大量的delete操作把整个索引块的数据都删了呢?索引中的索引条目仍然只

被标记为删除而没有被真正清空。设想下,如果这时候的索引关键字是一个不断增大的id,那么被标记为删除的索引条目就永远不会被重用,那树就不会不断增

长,也就出现了,表的数据空间减少了,而索引的数据空间却在不断增大的情况。由于索引的高度不断增加,访问索引数据时需要访问更多的索引块。

clustering_factor对

B树索引

的影响

对于clustering_factor来说,它是用来比较索引的顺序程度与表的杂乱排序程度的一个度量。Oracle在计算某个

clustering_factor时,会对每个索引键值查找对应到表的数据,在查找的过程中,会跟踪从一个表的数据块跳转到另外一个数据块的次数(当

然,它不可能真的这么做,源代码里只是简单的扫描索引,从而获得ROWID,然后从这些ROWID获得表的数据块的地址)。每一次跳转时,有个计数器就会

增加,最终该计数器的值就是clustering_factor。下图描述了这个原理。

在上图中,我们有一个表,该表有4个数据块,以及20条记录。在列N1上有一个索引,上图中的每个小黑点就表示一个索引条目。列N1的值如图所示。而N1

的索引的叶子节点包含的值为:A、B、C、D、E、F。如果oracle开始扫描索引的底部,叶子节点包含的第一个N1值为A,那么根据该值可以知道对应

的ROWID位于第一个数据块的第三行里,所以我们的计数器增加1。同时,A值还对应第二个数据块的第四行,由于跳转到了不同的数据块上,所以计数器再加

1。同样的,在处理B时,可以知道对应第一个数据块的第二行,由于我们从第二个数据块跳转到了第一个数据块,所以计数器再加1。同时,B值还对应了第一个

数据块的第五行,由于我们这里没有发生跳转,所以计数器不用加1。

在上面的图里,在表的每一行的下面都放了一个数字,它用来显示计数器跳转到该行时对应的值。当我们处理完索引的最后一个值时,我们在数据块上一共跳转了十次,所以该索引的clustering_factor为10。

注意第二个数据块,clustering_factor为8出现了4次。因为在索引里N1为E所对应的4个索引条目都指向了同一个数据块。从而使得

clustering_factor不再增长。同样的现象出现在第三个数据块中,它包含三条记录,它们的值都是C,对应的

clustering_factor都是6。

从clustering_factor的计算方法上可以看出,我们可以知道它的最小值就等于表所含有的数据块的数量;而最大值就是表所含有的记录的总行

数。很明显,clustering_factor越小越好,越小说明通过索引查找表里的数据行时需要访问的表的数据块越少。

所以我们可以得出结论,如果仅仅是为了降低索引的clustering_factor而重建索引没有任何意义。降低clustering_factor的关键在于重建表里的数据。事实上,生产环境下,我们甚至没有必要考虑

clustering_factor对索引访问的影响,这个是表数据分布决定的,如果想考虑,就得先创建索引,然后分析

clustering_factor,最后对表进行排序,再重新创建索引,可行性非常低。因此,这里只是作为研究讨论,实际环境下还是要结合具体情况进行分析。针对索引碎片和索引的"虚高",如果查询范围主要是通过unique index访问数据,可以不用理会

索引碎片和索引的"虚高",如果数据范围,主要是通过range scan的方式则需要重建索引,至于原理,相信读了笔者下面的文章后肯定会明白

http://czmmiao.iteye.com/blog/1481227

。关于索引是否需要重建,Oracle有这么一句话

Generally speaking, the need to rebuild b-tree indexes is very rare,

basically because a b-tree index is largely self-managed or

self-balanced.

如何查找出需要重建的索引

我们通过下面实验来具体看下如何查找需要重建的索引

准备实验环境如下

SQL> create table ind (id int,name varchar2(100));

Table created.

SQL> begin

2  for i in 1..10000 loop

3  insert into ind values(i,to_char(i)||'aaa');

4  end loop;

5  commit;

6  end;

7  /

PL/SQL procedure successfully completed.

SQL> create index ind_id_idx on ind(id);

Index created.

SQL> analyze index ind_id_idx validate structure;

Index analyzed.

注意:index_stats只能在同一个

session里先执行完analyze index indexname validate

structure后才能查到数据,在其他的session里查index_stats是查不到数据的,即使那个初始的session已经执行过

analyze index indexname validate structure。顺带提一句,

analyze index indexname validate structure会对整张表加排他锁,阻止表上的所有DML语句。

我们也可以使用online关键字,analyze index indexname validate structure online,这样就可以不对表加锁,但不会填充index_stats视图。

index_stats的主要相关字段如下

--LF_ROWS Number of values currently in the index

--LF_ROWS_LEN Sum in bytes of the length of all values

--DEL_LF_ROWS Number of values deleted from the index

--DEL_LF_ROWS_LEN Length of all deleted values

col name         heading 'Index Name'          format a30

col del_lf_rows  heading 'Deleted|Leaf Rows'   format 99999999

col lf_rows_used heading 'Used|Leaf Rows'      format 99999999

col ibadness     heading '% Deleted|Leaf Rows' format 999.99999

SQL> SELECT name,

2       del_lf_rows,

3      lf_rows - del_lf_rows lf_rows_used,

4      to_char(del_lf_rows / (lf_rows)*100,'999.99999') ibadness

5    FROM index_stats

6       where name = upper('&&index_name');

Deleted      Used % Deleted

Index Name                     Leaf Rows Leaf Rows Leaf Rows

------------------------------ --------- --------- ------------------------------

IND_ID_IDX                             0     10000     .00000

可以看到没有删除的索引

更新1000条记录

SQL> update ind set id=id+1 where id> 9000;

1000 rows updated.

SQL> commit;

Commit complete.

SQL> analyze index ind_id_idx validate structure;

Index analyzed.

SQL> col name         heading 'Index Name'          format a30

col del_lf_rows  heading 'Deleted|Leaf Rows'   format 99999999

col lf_rows_used heading 'Used|Leaf Rows'      format 99999999

col ibadness     heading '% Deleted|Leaf Rows' format 999.99999

SELECT name,

del_lf_rows,

lf_rows - del_lf_rows lf_rows_used,

to_char(del_lf_rows / (lf_rows)*100,'999.99999') ibadness

FROM index_stats

where name = upper('&&index_name');SQL> SQL> SQL> SQL> SQL>   2    3    4    5    6

old   6:        where name = upper('&&index_name')

new   6:        where name = upper('ind_id_idx')

Deleted      Used % Deleted

Index Name                     Leaf Rows Leaf Rows Leaf Rows

------------------------------ --------- --------- ------------------------------

IND_ID_IDX                          1000     10000    9.09091

删除的索引占了9.09%,如果删除的索引条目占了10~15%,则可以考虑重建索引或者coalesce

如何重建索引

重建索引有3种方法,具体如下:

1、删除重新建索引可以采用

PARALLEL,

NOLOGGING和

COMPUTE STATISTICS

进行处理,该方法是最慢的,最耗时的。一般不建议。

2、实验alter index .........rebuild命令重建

它使用原索引的叶子节点作为新索引的数据来源。我们知道,原索引的叶子节点的数据块通常都要比表里的数据块要少很多,因此进行的I/O就会减少;同时,由

于原索引的叶子节点里的索引条目已经排序了,因此在重建索引的过程中,所做的排序工作也要少的多。从oracle 8.1.6以后,ALTER

INDEX …

REBUILD命令可以添加ONLINE关键字。这使得在重建索引的过程中,用户可以继续对原来的索引进行修改,也就是说可以继续对表进行DML操作和删

除,但在11g之前,在开始和结束创建索引的时刻仍然会锁表。

由于新旧索引在建立时同时存在,因此,使用这种技巧则需要有额外的磁盘空间可临时使用,当索引建完后把老索引删除,如果没有成功,也不会影响原来的索引。利用这种办法,指定了tablespace关键字后

Alter index indexname rebuild  tablespace tablespacename

还可以用来将一个索引以到新的表空间。和

重建索引一样,

alter index indexname rebuild

也可以采用

PARALLEL,

NOLOGGING和

COMPUTE STATISTICS

进行处理

,使用

COMPUTE STATISTICS处理的好处在于

可以在重建索引的过程中,就生成CBO所需要的统计信息,这样就避免了索引创建完毕以后再次运行analyze或dbms_stats来收集统计信息。

这个命令的执行步骤如下:

首先,逐一读取现有索引,以获取索引的关键字。

其次,按新的结构填写临时数据段。

最后,一旦操作成功,删除原有索引树,降临时数据段重命名为新的索引。

需要注意的是alter index indexname rebuild 命令中必须使用tablespace字句,以保证重建工作是在现有索引相同的表空间进行。

3、使用alter index indexname coalesce命令或alter index indexname shrik space命令重建索引。该命令主要是

用来合并相邻的碎片,相比于rebuild,

有如下优点

1、always online,不需要锁索引

2、不需要消耗接近两倍的临时空间

3、当碎片比率小于25%时比rebuild产生更少的redo日志,当然我们可以在重建索引时将日志关闭。

4、

并不重建索引,只对叶子节点进行整合,不改变索引高度和分支节点数量。当我们重建索引

后,索引之间是紧密连接的,高度和分支数量都会改变。如果该索引列上继续进行DML操作,很可能导致树的重新增长、分裂,这是非常消耗资源的操作,同时由

于DML操作的继续,达到一定程度后,该索引很可能重新被认为需要rebuild,如此恶性循环。所以往往我们不建议重建索引,不希望重建索引而引起索引

高度和分支节点的重构,除非在需要迁移索引到另一个表空间时才选择rebuild。

Insert/update/delete causes the index to evolve over time as the

index splits and grows. When the index is rebuild it will become more

tightly packed; however as DML operations continue on the table the

index splits have to be redone again until the index reaches it's

equilibrium. As a result, the redo activity increases and the index

splits are now more likely to impact performance directly as we consume

more I/O, CPU, etc to serve the index restructuring. After a certain

period of time the index may again experience 'issues' and may be

re-flagged for a rebuild, causing the vicious cycle to continue.

Therefore it is often better to leave the index in its natural

equilibrium and/or at least prevent indexes from being rebuilt on a

regular basis.

5、10g以后引入了

alter index indexname shrik space命令,功能上

和alter index indexname coalesce一样,但经测试产生更多的redo日志(以实际测试环境为准)。

这边给出如下结论,帮助大家整理下

COALESCE、SHRINK和rebuild的区别

1、当索引中碎片率<=25%,COALESCE与SHRINK比rebuild的产生的redo日志少,消耗资源更少。两者相比之下SHRINK的成本会更高。

2、当

索引中碎片率>

25%的时,REBUILD的成本更小,产生的redo更少

对测试过程感兴趣的朋友可以参见链接

http://www.shujukuai.com/?p=102

http://www.oracledatabase12g.com/archives/alter-index-coalesce-vs-shrink-space.html

参考至:https://support.oracle.com/CSP/main/article?cmd=show&type=NOT&id=989093.1

http://space.itpub.net/?uid-9842-action-viewspace-itemid-324587

http://ustcer.blog.51cto.com/1135926/258625

http://www.itpub.net/thread-181890-1-1.html

http://www.shujukuai.com/?p=102

http://www.oracledatabase12g.com/archives/alter-index-coalesce-vs-shrink-space.html

mysql为什么要重建索引_深入理解重建索引相关推荐

  1. 怎么运用索引查处mysql表中的数据_深入理解MySQL数据库索引原理及实现,快速检索数据库 MySQL数据库使用教程...

    免费学习推荐: 一.索引的概念 1.索引是一个排序的列表,在这个列表中存储着索引的值和包含这个值的数据所在行的物理地址 (类似于C语言的链表通过指针指向数据记录的内存地址) . 2.使用索引后可以不用 ...

  2. java mysql索引_如何理解并正确使用MySql索引

    1.概述 索引是存储引擎用于快速查找记录的一种数据结构,通过合理的使用数据库索引可以大大提高系统的访问性能,接下来主要介绍在MySql数据库中索引类型,以及如何创建出更加合理且高效的索引技巧. 注:这 ...

  3. mysql主键创建非聚集索引_什么是聚集索引,非聚集索引,索引覆盖,回表,索引下推...

    聚集索引 我们先建如下的一张表 CREATE TABLE `student` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '学号',`name` var ...

  4. mysql+5.6+左连接_第5章 索引与算法

    5.1 InnoDB存储引擎索引概述 InnoDB常见支持:B+树索引.全文索引.哈希索引. B+树索引并不能找到一个给定键值的具体行,只能找到被查的数据所在的页.然后数据库通过把页读入到内存,再在内 ...

  5. 覆盖索引与联合索引_什么是覆盖索引?

    前言 要搞明白覆盖索引首先就得明白主键索引和辅助索引的区别,以及查询时引擎的工作方式. 当然,以上都是基于innoDB引擎来说. 主键索引与辅助索引的区别 相信大家也了解过这方面的知识,这里就不展开了 ...

  6. raid1重建时间_控制RAID重建时间的最佳方式

    问:控制RAID重建时间的最佳方式是什么? 答:决定RAID重建时间的控制方式和使用RAID重建磁盘驱动的时间长度的因素有很多,包括RAID的级别.磁盘的数量.磁盘的规模.磁盘的类型以及RAID功能实 ...

  7. mysql数据库约束详解_深入理解mysql数据库的约束

    摘要:MYSQL添加约束,删除约束添加列,修改列,删除列 添加主键约束: altertable表名addconstraint主键(形如:PK_表名)primarykey表名(主键字段); 添加外键约束 ...

  8. mysql 左外连接原理_深入理解SQL的四种连接-左外连接、右外连接、内连接、全连接...

    1.内联接(典型的联接运算,使用像 =  或 <> 之类的比较运算符).包括相等联接和自然联接. 内联接使用比较运算符根据每个表共有的列的值匹配两个表中的行.例如,检索 students和 ...

  9. mysql用help查看帮助_深入理解mysql帮助命令(help)

    在安装.管理和使用mysql过程中,你是不是需要记忆很多的mysql命令.而且对于新手来说,很不多的命令不知道该如何应用,对于老手来说很多命令时间长了忘记具体的用法. 其实mysql的帮助信息,已经给 ...

  10. mysql异步非阻塞方式_如何理解swoole异步非阻塞?

    传统的apache2handler或php-fpm本质上都是短生命周期(请求后释放资源)的FastCGI运行模式. 请求来了,master进程会调用worker进程来处理,处理完后释放资源. 假设你在 ...

最新文章

  1. 从 PoS 进化 SPoS:无能耗共识机制
  2. 2017android开发找不到工作,揭秘蒋多多2017生活现状,30岁找不到工作曾绝望自杀...
  3. python变量初始化的位置不当、程序结果可能会出现问题_解决tensorflow由于未初始化变量而导致的错误问题...
  4. 【python】python第二周作业
  5. 音频文件转码工具文档 目录 1. 音频文件转码 1 1.1. 简介 1 1.2. 转换命令示例 2 1.3. wav 文件转 16k 16bits 位深的单声道pcm文件 2 1.4. mp3 文件转
  6. 第 3 章 sqlmap - automatic SQL injection and database takeover tool
  7. matlab在有限差分法中的应用,MATLAB在有限差分法中的应用
  8. cjson构建_cJSON的构造和解析
  9. 在知乎上学 Python - 入门篇
  10. UNITY个人版设置深色主题
  11. 又是暴力裁员?腾讯 7 年老员工一朝被裁,官方回应了...
  12. 台达PLC无线通讯方案
  13. lightgbm 特征重要性选择 / 看所有特征哪个重要
  14. 目前国际上存在的主要安全标准
  15. 个人作品设计展示官网源码
  16. Java程序设计教程(第3版)雍俊海 全书例程-2
  17. android ratingbar 点击事件,Android RatingBar基本使用:
  18. 软件测试的基础知识(1)
  19. Linux下配置VSCode的C语言开发环境
  20. windows用户和组

热门文章

  1. FC1179U盘量产教程
  2. 电风扇计算机控制系统,语音识别电风扇控制系统设计.doc
  3. Java 金额转换帮助类(元转分)
  4. 局域网计算机用户名和密码怎么设置,win10系统设置局域网共享无需输入用户名和密码的解决教程...
  5. 1999-2019中国互联网发展二十年趋势
  6. win10专业版激活方法
  7. wow插件补充说明篇
  8. vue后台管理系统流程(面试必选)
  9. 电容笔能否替代Apple pencil?高性价比电容笔排行
  10. 计算机桌面保护时间的调整显示,电脑屏幕显示时间设置_电脑屏幕的显示时间...