分享

深度揭露Oracle索引使用中的限制

 舞·恋上您的舞 2010-08-02
众所周知,索引确实可以提高数据库的性能。但是大家对索引的使用限制却一口未提。笔者认为对于数据库索引的作用,应该分两面看。除了肯定其对数据库性能带来的正面影响外,还需要认识到其可能带来的负面影响。只有如此,数据库管理员才能够在正确的场合使用正确的索引。要知道有时候一个错误的索引可能引发死锁,并导致数据库性能的急剧下降或进程终止;而如果数据库管理员能够做出一个正确的判断的话,那么可以使那些本来要运行几个小时甚至一天的进程在几分钟之内就能够完成。所以这两个差距是一个天上、一个地下。故笔者希望通过这篇文章能够让各位读者了解索引在使用过程中的限制,了解索引并不是万能的。

    一、索引对数据库性能的影响跟数据选择性直接挂钩。

    当用户从数据表中查询数据时,Oracle数据库提供了两种查询的方式。一是从表中读取每一行,就是大家常说的全表扫描;二是通过ROWID一此读取一行。当表中记录比较多的时候,很明显第二种方式能够更快的定位记录内容。而索引其实就是建立在这个查询原理之上的。如现在某个表中有300多万条记录,而现在用户可能只需要了解其中的10条记录信息。此时如果使用索引标识读取的块,则可以执行比较少的I/O,数据库系统会很快找到用户所需要的内容。而如果没有使用索引的话,则需要读取表中所有的块。

    如果在这个表中加入了索引,那么到底对数据库的性能影响有多大呢?这个就不好说了,因为其跟很多因素相关。如跟数据选择性直接相关。如果用户的数据非常具有选择性,则表中家功能只有很少的行匹配索引值,则Oracle将能够快速查询匹配所引值得ROWID的索引,并且可以快速查询少量的相关表快。如还是上面这个表中,其如果存储有某个市的所有常住人口信息,其中身份证号码肯定是少不了的。如此时用户想根据身份证号码来查询某个人的信息时,那么数据库能够在很短的时间内给出响应。这主要是因为用户提供的数据非常具有选择性,基本上跟数据库中的索引值是一一对应的。而如果用户想通过出身年月信息来查询信息的话,则其数据库反映的速度就会比较慢了。

    可见索引对数据库性能的影响直接跟数据的选择性挂钩。这对于数据库管理员设计索引时很有启发性。如数据库管理员在设计索引时,最好能够选择哪些具有唯一性的字段或者重复性比较少的字段。如此的话,索引对于数据库性能来说才有比较大的价值。

    二、索引效果跟数据库中记录的具体存储位置相关。

    还是上面这张表中,如果现在用户想查找年龄超过100岁的老人,要对他们去进行慰问。假设现在符合这个条件的人只有10人。那么此时索引对数据库性能会有怎么样的影响呢?此时显然数据非常具有选择性,但是并不一定索引能够起到很好的效果。这还要看其具体存储的位置。如果这十条记录在硬盘中存储的物理位置比较近,如可能在同一个扇区之内,则此时索引对于数据库性能的影响就会比较大,能够在最短时间内找到符合条件的数据。但是如果相关的行在表中存储的位置并不互相靠近,则这个索引的效果就会逐渐减少。因为如果匹配索引值的数据分散在硬盘上的多个酷爱时,则必须从表中选择多个单独的块以满足查询。

    数据库管理员对于这一点要特别注意。因为此时如果数据库管理员查用了索引的话,那么很可能是画蛇添足。笔者建议,当数据库管理员发现数据分散在表的多个块的时候,最好是不要使用索引,而是执行全表扫描。此时执行扫描反而会比执行索引的效率更高。因为在执行全表扫描的时候,Oracle数据库系统会使用多块读取以加速扫描表。而如果采用索引的话,则其读取数据时是单块读取的。而由于数据存储在多个块中,所以其读取的速度反而会更慢。

    由此可见,Oracle数据库管理员在数据库设计与日常维护中,也要想办法能够让数据尽量存储在临近的位置。如尽量减少在同一个服务器中不要部署不同的应用服务,防止硬盘产生过多的磁盘碎片;如需要采用多块硬盘的话,则最好通过表空间把类似的表放在同一个表空间中,从而让相关的行在表zhognd存储位置尽量靠近,以提高索引的使用效果。也就是说,数据库管理员在使用索引的时候,为表中的字段建立了索引这只是其工作的第一步。在后续数据库维护与调整的过程中,仍然要注意数据存储位置对索引的影响。
通常情况下,索引可以提高数据库的性能。如通过索引,则Select、Update、、Delete语句的Where子句的性能可以从索引中获得收益。但是这并不是百分之百准确的。或者说,只有这些语句涉及到的行比较少的时候,这个原则是准确的。但是如果所涉及到的行比较多,则这个索引的应用反而会降低数据库的性能。

    如现在数据库系统中有一张表,其中包含了300万条记录。而用户现在需要利用Delete语句删除其中100万条记录。如想要把记录创建日期为2005年12月31日前的数据全部删除掉。此时虽然采用了Where子句的限制条件,但是这个时候因为删除的数据量太多,其并不能够从索引中获取什么好处。因为利用delete语句删除记录的时候,同时需要删除相关的索引。当Delete语句需要删除将近表中一半的记录的时候,同时需要删除跟这个表相关的近一半的索引,这个过程是非常耗时的。为此大量行的Delete操作会因为表中存在索引而降低其执行速度。另外Insert语句也会有类似的现象。通常情况下,增加索引会降低Insert语句的执行新能。因为在执行insert语句的时候,由于索引的存在,数据库需要同时往数据表与索引表中插入数据。为此,从理论上来说,数据库表中的每个索引都回使得对这个表进行Insert操作时速度减慢两倍;而在这个数据表上使用两条索引则会使得插入速度减慢一倍。

    可见并不是所有语句或者操作都能够从索引中获得收益。为此数据库管理员必须要了解索引跟一些常用命令之间的冲突。只有如此数据库管理员才能够在索引给某些操作带来的收益与损失之间取得一个均衡,并根据相关的操作来调整索引。对于这一点笔者有如下几个建议,大家可以参考一下。

    一是当需要网一个表中插入大量数据的时候,最好能够先把索引取消,以提高插入的速度。如现在数据库管理员需要往表Product中添加记录的话,无论其采用什么方式,如采用Select into语句,还是采用图形化的导入工具都好。当需要插入的记录比较多的时候,最好先把索引禁用掉。此时数据库只需要在数据表中插入数据即可,而不用维护索引表。等到数据导入完成之后,再起用这个索引。此时数据库会重建这些记录的索引。这是大部分数据库管理员在数据插入的过程中常用的手段。可以明显提高数据库的插入性能。

    二是当因为某些原因需要清空数据库表中的记录时,如果这张数据表中的记录比较多时,则可以考虑一下先把表中的索引取消掉,然后再执行删除操作。如此的话数据库系统在删除数据的时候,就不用同时维护数据表与索引表了。故可以成倍提高Delete的操作效率。等到删除操作执行完毕后,再启用索引。

    当受影响的记录比较多时,上面这两个建议可以明显的提高数据库的执行性能。特别是在应用系统初始化的过程中,可能需要导入大量的初始化记录。有时候可能发现数据导入有错误需要整张表清空等等。此时如果先把索引禁用掉的话,则数据库管理员会发现,期初数据导入会变得顺利许多。

    数据库系统强制性的要求。即使不采用这些建议,数据库最终也可以完成相关的任务。只是其速度上可能会有差异。而且随着记录的不同,这个差异有时候可能会相差几十个小时。总之笔者认为作为一个优秀的数据库管理员,应该了解索引在不同情况下对数据库系统的影响。大丈夫能屈能伸。在必要的情况下,数据库管理员要敢于取消索引,以提高某些操作的性能。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多