1年前写的一篇总结,今天翻出来发到博客上去。
在测试中发现一个存储过程中的一段INSERT...SELECT...操作非常耗时,每次都要跑将近两个小时,于是试着去探究原因。首先看了一下SELECT操作有没有问题,单独跑了一下SELECT语句用了不到10秒钟就跑完了,而且数据量只有50多万,这么小的数据量怎么会导致INSERT消耗那么长时间呢?于是试着加上append提示,结果还是不能解决问题。想了想有可能是这个表有什么属性比较特殊,因此自己建了个表结构相同的测试表,把数据向测试表中INSERT,结果不到20秒钟就跑完了,于是确定一定是表的原因。以前在帮同事造压力测试数据的时候也遇到过INSERT相当慢的情况,不过那次是因为数据量非常大并且没有把索引先disable掉,这次的数据量这么小,不会也是索引的原因吧?突然想到这次插入的表是一个分区表,而在分区表上建索引就有两种不同的方式:全局索引和局部索引,于是查了一下这个表建的是什么索引,一看是全局索引,于是自己觉得应该是找到了答案。
局部索引和全局索引的区别如下图所示:
http://s15/mw690/6ff05a2cgd2d1c68cd4fe&690
通常来讲,局部索引多用于数据仓库,全局索引多用于OLTP系统。局部索引是在每个表分区内创建一个独立的索引树,互不影响;而全局索引是基于所有分区创建一个大的索引树。实验如下:
首先创建一个分区表:
ETL@CTRTEST> CREATE TABLE liutest(
yyyymmdd DATE
NOT NULL,
member_id
VARCHAR2(32) NOT NULL
)
PARTITION BY RANGE (yyyymmdd)
( PARTITION P20101228 VALUES LESS THAN (TO_DATE('2010-12-29
00:00:00','YYYY-MM-DD HH24:MI:SS')) ,
PARTITION P20101229 VALUES LESS
THAN (TO_DATE('2010-12-30 00:00:00','YYYY-MM-DD HH24:MI:SS'))
,
PARTITION P20101230 VALUES LESS
THAN (TO_DATE('2010-12-31 00:00:00','YYYY-MM-DD HH24:MI:SS'))
,
PARTITION P20101231 VALUES LESS
THAN (TO_DATE('2011-01-01 00:00:00','YYYY-MM-DD HH24:MI:SS'))
);
Table created.
然后创建一个局部索引:
ETL@CTRTEST> CREATE INDEX liutest_IND ON
liutest(member_id) LOCAL;
Index created.
然后查一下为这个索引创建了多少个段:
ETL@CTRTEST> select
segment_name,partition_name,segment_type from dba_segments where
segment_name='LIUTEST_IND';
SEGMENT_NAME PARTITION_NAME
SEGMENT_TYPE
-------------------------------- ------------------------------
------------------
LIUTEST_IND P20101228 INDEX
PARTITION
LIUTEST_IND P20101229 INDEX
PARTITION
LIUTEST_IND P20101230 INDEX
PARTITION
LIUTEST_IND