我们有的一个应用系统需要在某些时段向其日志记录表中集中插入数据。
通过观察发现该表的一些特征;
1.主键是使用SEQUENCE单调递增生成的。
2.对日志表的查询不会扫描多条连续记录(主键)
当然最为直接的办法就是去掉索引、主键。但是该主键不能停止或直接删除。
在这种情况下,试图将该主键改造成为REVERSE类型的主键,虽然数据库只有一个单实例。
在测试数据库上进行相关实验:
背景:
一张表(LARRY_TEST)中含有1100000条数据,另外建立了一张和LARRY_TEST结构完全相同的表(LARRY_TESTINSERT)。然后创建主键:
将LARRY_TEST的数据插入到测试表LARRY_TESTINSERT中
然后清除(TRUNCATE TABLE)该表记录,将主键pk_test_insert转换成REVERSE的
检查该主键的类型
我们发现该主键已经是REVERSE类型的了。开始插入数据:
结论:
我们不难发现,后者在插入数据时争用有所下降(减少了插入操作的索引热点块),执行的插入效率有所提高(减少了近8秒钟)。
同时,这种通过序列、时间戳或按某种规则单调生成主键的表,可以因为使用REVERSE(反转)类型索引来有效的降低索引“单向右增长”(right-growing index)的可能性,即会影响到响应时间和吞吐量。如果在基于RAC的环境中,REVERSE类型的索引会更为适用。
但要注意,使用REVERSE类型的索引在查询操作时会被限制使用基于索引区间的扫描(index range scans).
在数据库的优化中你经常会发现没有绝对的好,也没有绝对的差。
通过观察发现该表的一些特征;
1.主键是使用SEQUENCE单调递增生成的。
2.对日志表的查询不会扫描多条连续记录(主键)
当然最为直接的办法就是去掉索引、主键。但是该主键不能停止或直接删除。
在这种情况下,试图将该主键改造成为REVERSE类型的主键,虽然数据库只有一个单实例。
在测试数据库上进行相关实验:
背景:
一张表(LARRY_TEST)中含有1100000条数据,另外建立了一张和LARRY_TEST结构完全相同的表(LARRY_TESTINSERT)。然后创建主键:
ALTER TABLE larry_testinsert ADD CONSTRAINT pk_test_insert PRIMARY KEY (terminal_id);
将LARRY_TEST的数据插入到测试表LARRY_TESTINSERT中
SQL> insert /*+append*/ into larry_testinsert select * from larry_test;
1100000 rows created.
Elapsed: 00:01:30.86
Statistics
----------------------------------------------------------
1908 recursive calls
61366 db block gets
11367 consistent gets
8191 physical reads
72506424 redo size
612 bytes sent via SQL*Net to client
568 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
4 sorts (memory)
1 sorts (disk)
1100000 rows processed
SQL> commit;
Commit complete.
Elapsed: 00:00:00.14
1100000 rows created.
Elapsed: 00:01:30.86
Statistics
----------------------------------------------------------
1908 recursive calls
61366 db block gets
11367 consistent gets
8191 physical reads
72506424 redo size
612 bytes sent via SQL*Net to client
568 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
4 sorts (memory)
1 sorts (disk)
1100000 rows processed
SQL> commit;
Commit complete.
Elapsed: 00:00:00.14
然后清除(TRUNCATE TABLE)该表记录,将主键pk_test_insert转换成REVERSE的
SQL> alter index pk_test_insert
rebuild reverse;
Index altered
Executed in 0.469 seconds
Index altered
Executed in 0.469 seconds
检查该主键的类型
SQL> select INDEX_NAME,INDEX_TYPE from dba_indexes where index_name ='PK_TEST_INSERT';
INDEX_NAME INDEX_TYPE
------------------------------ ---------------------------
PK_TEST_INSERT NORMAL/REV
Elapsed: 00:00:00.09
INDEX_NAME INDEX_TYPE
------------------------------ ---------------------------
PK_TEST_INSERT NORMAL/REV
Elapsed: 00:00:00.09
我们发现该主键已经是REVERSE类型的了。开始插入数据:
SQL> insert /*+append*/ into larry_testinsert select * from larry_test;
1100000 rows created.
Elapsed: 00:01:22.90
Statistics
----------------------------------------------------------
1923 recursive calls
61328 db block gets
9872 consistent gets
8197 physical reads
72446936 redo size
614 bytes sent via SQL*Net to client
568 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
1 sorts (memory)
1 sorts (disk)
1100000 rows processed
SQL> commit;
Commit complete.
Elapsed: 00:00:00.01
1100000 rows created.
Elapsed: 00:01:22.90
Statistics
----------------------------------------------------------
1923 recursive calls
61328 db block gets
9872 consistent gets
8197 physical reads
72446936 redo size
614 bytes sent via SQL*Net to client
568 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
1 sorts (memory)
1 sorts (disk)
1100000 rows processed
SQL> commit;
Commit complete.
Elapsed: 00:00:00.01
结论:
我们不难发现,后者在插入数据时争用有所下降(减少了插入操作的索引热点块),执行的插入效率有所提高(减少了近8秒钟)。
同时,这种通过序列、时间戳或按某种规则单调生成主键的表,可以因为使用REVERSE(反转)类型索引来有效的降低索引“单向右增长”(right-growing index)的可能性,即会影响到响应时间和吞吐量。如果在基于RAC的环境中,REVERSE类型的索引会更为适用。
但要注意,使用REVERSE类型的索引在查询操作时会被限制使用基于索引区间的扫描(index range scans).
在数据库的优化中你经常会发现没有绝对的好,也没有绝对的差。
人生亦如此 -:)
本文转自Be the miracle!博客51CTO博客,原文链接http://blog.51cto.com/miracle/55538如需转载请自行联系原作者
Larry.Yue