h1.오라클 제공하는 인덱스 유형
'B'는 Binary 가 아닌 Balanced 를 의미
키 값을 이용해서 개별적인 로우 또는 로우의 특정 범위를 빠르게 접근할 수 있도록 해주며,
몇 번의 읽는 과정만으로 정확한 로우를 서칭
B*Tree 구조로 저장되는 테이블
IOT 데이터는 기본 키에 의해 정렬되어 저장된다.
클러스터 키를 인덱싱 하는 것
B*Tree 인덱스 - 테이블 로우를 가리키는 인덱스 키 가짐
B*Tree 클러스터 인덱스 - 로우가 포함된 블록을 가리키는 클러스터 키 가짐
올림차순 인덱스 - 작은 값부터 큰 값으로 오름차순으로 정렬 ( Default )
내림차순 인덱스 - 큰 값부터 작은 값으로 내림차순으로 정렬된 데이터를 위한 인덱스
키 값을 뒤 칼럼 값에서부터 역순으로 뒤집은 B*Tree 인덱스
계속 증가하는 값에 대한 인덱스를 고르게 분산하기 위한 인덱스
리버스 인덱스 구성을 통해서 근접하던 값들이 다수의 블록에 분산 저장됌
테이블 칼럼 값 - 987500, 987501, 987502
리버스 키 인덱스 - 205789, 105789, 005789
B*Tree Index : 인덱스 엔트리 : 테이블 로부 = 1:1
Bitmap Index : 인덱스 엔트리 : 테이블 로부 = 1:M
Cardinality가 작은 읽기 전용 데이터에 적합(DW 용)
INSERT,UPDATE,DELETE 에 따른 비트냅 인덱스 동시성 이슈로 OLTP 에 부적합
테이블 속성의 반정규화를 대신하여 인덱스 구조를 통해 반정규화하는 것
두 개 이상의 테이블 조인 결과에 대해 비트냅 인덱스 구성(OLTP 에 부적합)
칼럼값 자체가 아니라 컬럼에 대한 함수의 계산된 결과를 저장하는 B*Tree 또는 비트앱 인덱스
오라클 내부 또는 외부 사용자가 만들어서 저장하는 인덱스 ( 오라클 텍스트 인덱스 )
[그림 11-1] B*Tree 인덱스 구조
CREATE INDEX I ON T ( X, Y )
SQL> set autotrace traceonly statistics
SQL> SELECT ID
2 FROM BIG_TABLE WHERE ID = 42 ;
no rows selected
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
3 consistent gets <===
0 physical reads
0 redo size
319 bytes sent via SQL*Net to client
481 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed
SQL> SELECT ID
2 FROM BIG_TABLE WHERE ID = 12345 ;
no rows selected
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
3 consistent gets <===
0 physical reads
0 redo size
319 bytes sent via SQL*Net to client
481 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed
SQL> SELECT ID
2 FROM BIG_TABLE WHERE ID = 1234567 ;
no rows selected
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
3 consistent gets <==
0 physical reads
0 redo size
319 bytes sent via SQL*Net to client
481 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed
SQL> select owner, index_name, BLEVEL from dba_indexes where index_name='BIG_TABLE_PK';
OWNER INDEX_NAME BLEVEL
------------------------------ ------------------------------ ----------
OPS$ORACLE BIG_TABLE_PK 2
SQL> create table t
2 as
3 select * from all_objects
4 where rownum <= 50000 ;
Table created.
SQL> create index t_idx on t ( owner, object_type, object_name );
Index created.
SQL> analyze index t_idx validate structure ;
Index analyzed.
SQL> create table idx_stats
2 as
3 select 'noncompressed' what, a.* from index_stats a ;
Table created.
SQL> !cat compress_index_test.sql
drop index t_idx ;
create index t_idx on t ( owner, object_type, object_name ) compress &1 ;
analyze index t_idx validate structure ;
insert into idx_stats select 'compress &1', a.* from index_stats a ;
SQL> @compress_index_test.sql
Index dropped.
Enter value for 1: 1
old 1: create index t_idx on t ( owner, object_type, object_name ) compress &1
new 1: create index t_idx on t ( owner, object_type, object_name ) compress 1
Index created.
Index analyzed.
Enter value for 1: 1
old 1: insert into idx_stats select 'compress &1', a.* from index_stats a
new 1: insert into idx_stats select 'compress 1', a.* from index_stats a
1 row created.
SQL> commit ;
Commit complete.
이하 생략
SQL> set linesize 150
SQL> select what, height, lf_blks, br_blks, btree_space, opt_cmpr_count, opt_cmpr_pctsave
2 from idx_stats ;
WHAT HEIGHT LF_BLKS BR_BLKS BTREE_SPACE OPT_CMPR_COUNT OPT_CMPR_PCTSAVE
------------- ---------- ---------- ---------- ----------- -------------- ----------------
noncompressed 3 347 3 2793096 2 28
compress 1 3 308 3 2480644 2 19
compress 2 3 247 3 1994108 2 0
compress 3 3 387 3 3110748 2 35
SQL> select 90101, dump(90101,16) from dual
2 union all
3 select 90102, dump(90102,16) from dual
4 union all
5 select 90103, dump(90103,16) from dual ;
90101 DUMP(90101,16)
---------- ---------------------
90101 Typ=2 Len=4: c3,a,2,2
90102 Typ=2 Len=4: c3,a,2,3
90103 Typ=2 Len=4: c3,a,2,4
SQL> drop table t;
Statement Processed.
Elapsed: 00:00:00.171
SQL> create table t
as
select 0 id, a.*
from all_objects a
where 1=0;
Statement Processed.
SQL> CREATE INDEX XAK1_T ON T ( ID , OBJECT_ID) REVERSE TABLESPACE TOOLS;
Statement Processed.
SQL> SELECT INDEX_TYPE FROM DBA_INDEXES WHERE INDEX_NAME ='XAK1_T';
INDEX_TYPE
---------------------------
NORMAL/REV
1 rows selected.
begin
for x in ( select rownum r, all_objects.* from all_objects )
loop
insert into t
( id, owner, object_name, subobject_name,
object_id, data_object_id, object_type, created,
last_ddl_time, timestamp, status, temporary,
generated, secondary )
values
( s_1.nextval, x.owner, x.object_name, x.subobject_name,
x.object_id, x.data_object_id, x.object_type, x.created,
x.last_ddl_time, x.timestamp, x.status, x.temporary,
x.generated, x.secondary );
if( mod(x.r,100)= 0 )
then
commit ;
end if;
end loop;
commit;
end;
SQL> SELECT MIN(OBJECT_ID), MAX(OBJECT_ID) FROM T;
MIN(OBJECT_ MAX(OBJECT_
----------- -----------
2 954732
1 rows selected.
SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME =>'OPS$ORACLE', TABNAME=>'T', CASCADE => TRUE)
PL/SQL executed.
SQL> ALTER SESSION SET STATISTICS_LEVEL = ALL;
Statement Processed.
SELECT /*+ gather_plan_statistics */ *
FROM T A
WHERE OBJECT_ID = 954732 ;
select * from table( dbms_xplan.display_cursor( null, null, 'ALLSTATS LAST'));
------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
------------------------------------------------------------------------------------
|* 1 | TABLE ACCESS FULL| T | 1 | 1 | 1 |00:00:00.02 | 880 |
------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("OBJECT_ID"=954732)
SELECT /*+ gather_plan_statistics */ *
FROM T A
WHERE ID = 954730 ;
select * from table( dbms_xplan.display_cursor( null, null, 'ALLSTATS LAST'));
------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
------------------------------------------------------------------------------------------------
| 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 1 | 0 |00:00:00.01 | 2 |
|* 2 | INDEX RANGE SCAN | XAK1_T | 1 | 1 | 0 |00:00:00.01 | 2 |
------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID"=954730)
SELECT /*+ gather_plan_statistics INDEX(A) */ *
FROM T A
WHERE OBJECT_ID = 954732 ;
select * from table( dbms_xplan.display_cursor( null, null, 'ALLSTATS LAST'));
------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
------------------------------------------------------------------------------------------------
| 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 1 | 1 |00:00:00.03 | 259 |
|* 2 | INDEX FULL SCAN | XAK1_T | 1 | 1 | 1 |00:00:00.03 | 258 |
------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OBJECT_ID"=954732)
filter("OBJECT_ID"=954732)
*Restrictions on Reverse Indexes Reverse indexes are subject to the following restrictions:
You cannot specify NOSORT with this clause.
You cannot reverse a bitmap index or an index on an index-organized table.
SQL> !cat reverse_test.sql
create table t
as
select 0 id, a.*
from all_objects a
where 1=0 ;
alter table t
add constraint t_pk
primary key (id)
using index ( create index t_pk on t(id) &index_type tablespace tools );
create sequence s cache 1000 ;
SQL> @reverse_test.sql
create table t
*
ERROR at line 1:
ORA-00955: name is already used by an existing object
Enter value for index_type:
old 4: using index ( create index t_pk on t(id) &index_type tablespace tools )
new 4: using index ( create index t_pk on t(id) tablespace tools )
Table altered.
Sequence created.
SQL> !cat cr_do_sql.sql
create or replace procedure do_sql
as
begin
for x in ( select rownum r, all_objects.* from all_objects )
loop
insert into t
( id, owner, object_name, subobject_name,
object_id, data_object_id, object_type, created,
last_ddl_time, timestamp, status, temporary,
generated, secondary )
values
( s.nextval, x.owner, x.object_name, x.subobject_name,
x.object_id, x.data_object_id, x.object_type, x.created,
x.last_ddl_time, x.timestamp, x.status, x.temporary,
x.generated, x.secondary );
if( mod(x.r,100)= 0 )
then
commit ;
end if;
end loop;
commit;
end;
/
SQL> @cr_do_sql.sql
Procedure created.
SQL> show error
No errors.
SQL>
SQL> set timing on
SQL> exec do_sql
PL/SQL procedure successfully completed.
Elapsed: 00:00:06.83
SQL>
SQL> drop sequence s ;
Sequence dropped.
Elapsed: 00:00:00.03
SQL> drop table t;
Table dropped.
Elapsed: 00:00:00.05
SQL> @reverse_test.sql
Table created.
Elapsed: 00:00:00.07
Enter value for index_type: reverse
old 4: using index ( create index t_pk on t(id) &index_type tablespace tools )
new 4: using index ( create index t_pk on t(id) reverse tablespace tools )
Table altered.
Elapsed: 00:00:00.02
Sequence created.
Elapsed: 00:00:00.00
SQL> exec do_sql
PL/SQL procedure successfully completed.
Elapsed: 00:00:07.19
-- 2명이서
SQL> drop table t;
Table dropped.
Elapsed: 00:00:00.13
SQL> drop sequence s ;
Sequence dropped.
Elapsed: 00:00:00.01
SQL> @reverse_test.sql
Table created.
Elapsed: 00:00:00.07
Enter value for index_type:
old 4: using index ( create index t_pk on t(id) &index_type tablespace tools )
new 4: using index ( create index t_pk on t(id) tablespace tools )
Table altered.
Elapsed: 00:00:00.02
Sequence created.
Elapsed: 00:00:00.01
SQL> exec do_sql
PL/SQL procedure successfully completed.
Elapsed: 00:00:08.38
SQL> set timing on
SQL> exec do_sql
PL/SQL procedure successfully completed.
Elapsed: 00:00:08.41
SQL> drop sequence s ;
Sequence dropped.
Elapsed: 00:00:00.01
SQL> drop table t;
Table dropped.
Elapsed: 00:00:00.23
SQL> @reverse_test.sql
Table created.
Elapsed: 00:00:00.07
Enter value for index_type: reverse
old 4: using index ( create index t_pk on t(id) &index_type tablespace tools )
new 4: using index ( create index t_pk on t(id) reverse tablespace tools )
Table altered.
Elapsed: 00:00:00.03
Sequence created.
Elapsed: 00:00:00.00
SQL> select index_type from dba_indexes where index_name ='T_PK';
INDEX_TYPE
---------------------------
NORMAL/REV
Elapsed: 00:00:00.03
SQL> exec do_sql;
PL/SQL procedure successfully completed.
Elapsed: 00:00:08.26
SQL> exec do_sql;
PL/SQL procedure successfully completed.
Elapsed: 00:00:08.19
[표11-2] 두명의 사용자 환경에서 리버스 키에 대한 PL/SQL과 Pro*C비교
[표11-2] 5명의 사용자 환경에서 리버스 키에 대한 PL/SQL과 Pro*C비교
[표11-2] 10명의 사용자 환경에서 리버스 키에 대한 PL/SQL과 Pro*C비교