A-A+

有关索引-B树索引

2013年03月24日 BasicKnowledge 暂无评论 阅读 2,573 次

B树索引
B树索引基础知识:
表中的行标示符(rowid)和相关的列值存储在一个平衡的树状结构中。

使用B树索引的原因:
1)提供sql语句的性能
2)强制执行主键和唯一键约束的唯一性
3)减少通过主键和外键约束关联的父表和子表间潜在的锁表问题,即就是外键列上缺少B树索引可能导致表锁定问题发生

注意事项:
1)建议为索引创建单独的索引表空间便于管理,创建时建议使用统一大小的区减少对象创建和删除时的碎片;如果该索引表空间的索引倾向于扫描类的索引,建议选用大的数据块,以减少I/O。
2)从oracle11gr2开始,在创建表的时候还没有向表中插入数据时,相关的段和区会被推迟创建。
3)使一个索引不可见(invisible)在oracle11g开始支持。而且不可见索引仍然由oracle维护,但是查询优化器在确定执行计划的时候不考虑她。
4)如果需要外键约束,则必须使用主键或唯一键约束。
5)删除主键索引,必须先删除或禁用主机约束。在删除或禁用主键约束时,可以选择不删除相关索引。语法如下:
alter table test drop constraint test_pk keep index;
6)使一个索引不可用(unusable),oracle将不会再维护这个索引,并且优化器也不会考虑该索引。如果需要再次将一个不可用的索引再次可用,那么必须将其重建。
7)外键必须创建B树索引,不然当对子表操作时,父表会被全锁定。如何查看数据库哪些外键缺失索引,可见脚本:scripts:查看外键索引是否存在(http://www.yallonking.com/tools-scripts/2013/02/737.html)以及《外键缺失索引导致锁表的问题》(http://www.yallonking.com/database/troubleshooting/2013/02/739.html)

oracle如何使用B树索引:
1)所有数据都在索引块中
2)索引中不包含所有信息
3)只有表被访问

创建索引前,估算B树索引的大小:

SQL> sho user
USER is "SYS"
SQL> conn test/test 
Connected.
SQL> sho user
USER is "TEST"
SQL> select * from test;

no rows selected

SQL> drop table test;

Table dropped.

SQL> create table test as select rownum id,'yallonking' name from dual connect by level <= 1000;

Table created.

SQL> select * from test where rownum<10;

		ID NAME
---------- ----------
		1 yallonking
		2 yallonking
		3 yallonking
		4 yallonking
		5 yallonking
		6 yallonking
		7 yallonking
		8 yallonking
		9 yallonking

9 rows selected.

SQL> conn /as sysdba
Connected.
SQL> set serverout on
SQL> exec dbms_stats.gather_table_stats('TEST','TEST');

PL/SQL procedure successfully completed.

SQL> select to_char(LAST_ANALYZED,'yyyy/mm/dd hh24:mi:ss') from dba_tables where TABLE_NAME ='TEST';

TO_CHAR(LAST_ANALYZ
-------------------
2013/03/24 07:51:44
SQL> variable used_bytes number
SQL> variable alloc_bytes number
SQL> exec dbms_space.create_index_cost('create index test_id on test(id)',:used_bytes,:alloc_bytes);
BEGIN dbms_space.create_index_cost('create index test_id on test(id)',:used_bytes,:alloc_bytes); END;

*
ERROR at line 1:
ORA-00942: table or view does not exist
ORA-06512: at "SYS.DBMS_SPACE", line 1731
ORA-06512: at "SYS.DBMS_SPACE", line 1752
ORA-06512: at line 1

注:此处版本不支持

SQL> select * from gv$version;

INST_ID BANNER
---------- ----------------------------------------------------------------
		1 Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
		1 PL/SQL Release 10.2.0.1.0 - Production
		1 CORE 10.2.0.1.0      Production
		1 TNS for Linux: Version 10.2.0.1.0 - Production
		1 NLSRTL Version 10.2.0.1.0 - Production

重新在11g版本中重复以上步骤

SQL> select * from gv$version;

INST_ID BANNER
---------- --------------------------------------------------------------------------------
		1 Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
		1 PL/SQL Release 11.2.0.3.0 - Production
		1 CORE 11.2.0.3.0      Production
		1 TNS for Linux: Version 11.2.0.3.0 - Production
		1 NLSRTL Version 11.2.0.3.0 - Production

SQL> create table test as select rownum id,'yallonking' name from dual connect by level <= 1000;

Table created.

SQL> select * from test where rownum<10;

		ID NAME
---------- ----------
		1 yallonking
		2 yallonking
		3 yallonking
		4 yallonking
		5 yallonking
		6 yallonking
		7 yallonking
		8 yallonking
		9 yallonking

9 rows selected.

SQL> set serverout on
SQL> exec dbms_stats.gather_table_stats('SYS','TEST');

PL/SQL procedure successfully completed.

SQL> select to_char(LAST_ANALYZED,'yyyy/mm/dd hh24:mi:ss') from dba_tables where TABLE_NAME ='TEST';

TO_CHAR(LAST_ANALYZ
-------------------
2013/03/24 22:58:48

SQL> variable used_bytes number
SQL> variable alloc_bytes number
SQL> exec dbms_space.create_index_cost('create index test_id on test(id)',:used_bytes,:alloc_bytes);

PL/SQL procedure successfully completed.

SQL> print :used_bytes

USED_BYTES
----------
	4000

SQL> print :alloc_bytes

ALLOC_BYTES
-----------
	65536

SQL> declare
2  l_index_ddl varchar(1000);
3  l_used_bytes number;
4  l_allocated_bytes number;
5  begin
6  dbms_space.create_index_cost(
7  ddl =>'create index test_id on test(id)',
8  used_bytes=>l_used_bytes,
9  alloc_bytes =>l_allocated_bytes);
10  dbms_output.put_line('used ='||l_used_bytes||'bytes'
11  ||'  allocated= '|| l_allocated_bytes || 'bytes');
12  end;
13  /
used =4000bytes  allocated= 65536bytes

PL/SQL procedure successfully completed.

以下在索引创建完成后,在10g和11g中均可查看oracle给该索引分配的空间大小:

SQL> create index test_id on test(id);

Index created.

SQL> COL SEGMENT_NAME FOR A20
SQL> select a.segment_name,a.tablespace_name,b.table_name,a.bytes/1024/1024 mbytes,a.blocks
2  from dba_segments a, dba_indexes b
3  where a.segment_name = b.index_name
4  and a.segment_type = 'INDEX'
5  and b.index_name='TEST_ID'
6  group by a.tablespace_name,b.table_name,a.segment_name,a.blocks,a.bytes/1024/1024
7  order by a.bytes/1024/1024 desc,a.tablespace_name,table_name;

SEGMENT_NAME         TABLESPACE_NAME                TABLE_NAME                         MBYTES     BLOCKS
-------------------- ------------------------------ ------------------------------ ---------- ----------
TEST_ID              SYSTEM                         TEST                                .0625          8

SQL> SELECT 0.0625*1024*1024 FROM DUAL;

0.0625*1024*1024
----------------
		65536

给我留言

Copyright © YallonKing 保留所有权利.   Theme  Ality

用户登录

分享到: