- 현재 파티션 정보 확인
select partition_name, subpartition_count,high_value, tablespace_name, num_rows,blocks,avg_row_len
from dba_tab_partitions
where table_owner='HR'
and table_name='SAL_EMP';

- 데이터를 입력하려고 했지만 파티션 키 컬럼의 값이 어느 파티션에도 부합하지 않아 오류가 발생한다.
insert into hr.sal_emp(employee_id, last_name, salary, department_id)
values(300,'oracle',30000,20);

- maxvalue 파티션 추가
alter table hr.sal_emp add partition pmax values less than(maxvalue);
- 추가된 파티션 정보 확인
select partition_name, subpartition_count,high_value, tablespace_name, num_rows,blocks,avg_row_len
from dba_tab_partitions
where table_owner='HR'
and table_name='SAL_EMP';

- 다시 데이터를 입력해보면 정상적으로 입력이 된다.
insert into hr.sal_emp(employee_id, last_name, salary, department_id)
values(300,'oracle',30000,20);

- 입력값 확인
select * from hr.sal_emp partition(pmax);

- 새로운값 입력, 입력된 값은 pmax 파티션으로 입력된다.
insert into hr.sal_emp(employee_id, last_name, salary, department_id)
values(400,'itwill',50000,10);
select * from hr.sal_emp partition(pmax);

- 40000을 기준으로 split 하기
alter table hr.sal_emp split partition pmax at(40000) into(partition p5, partition pmax);
- split된 파티션 정보 확인
select partition_name, subpartition_count,high_value, tablespace_name, num_rows,blocks,avg_row_len
from dba_tab_partitions
where table_owner='HR'
and table_name='SAL_EMP';

- 병합하기전 파티션 값들 확인
select * from hr.sal_emp partition(p4);
select * from hr.sal_emp partition(p5);

- p4,p5를 병합하는데 병합 파티션은 p5로 한다.(병합시 partitions로 복수형임을 주의하자)
alter table hr.sal_emp merge partitions p4,p5 into partition p5;
- 파티션 정보를 확인해보면 기존 p4는 없어지고 병합된 파티션은 통계정보가 수집되어있다.
select partition_name, subpartition_count,high_value, tablespace_name, num_rows,blocks,avg_row_len
from dba_tab_partitions
where table_owner='HR'
and table_name='SAL_EMP';

- 병합된 데이터 확인
select * from hr.sal_emp partition(p5);

EXCHANGE PARTITION 명령어는 데이터를 물리적으로 이동하지 않고, 메타데이터만 교환합니다. 즉, 파티션 p5의 데이터는 물리적으로 그대로 남아있고, 논리적으로만 hr.exchange_emp 테이블의 데이터로 간주됩니다. 데이터의 물리적 저장 위치는 변경되지 않으며, 그래서 ROWID도 변하지 않습니다.- exchange할 비어있는 테이블 생성
create table hr.exchange_emp
as
select employee_id, last_name, salary, department_id
from hr.employees
where 1=2;
- p5 파티션 데이터값 확인
select * from hr.sal_emp partition(p5);

- p5테이블과 exchange_emp 테이블을 exchange(내부적으로는 rename작동이라고 한다)
alter table hr.sal_emp exchange partition p5 with table hr.exchange_emp;

- exchange 되었기 때문에 p5 파티션는 비어있다.
select * from hr.sal_emp partition(p5);

- p5에 있던 값이 조회된다
select * from hr.exchange_emp;

- 다시 exchange_emp에서 p5로 exchange
alter table hr.sal_emp exchange partition p5 with table hr.exchange_emp;
- exchange된 값 확인
select * from hr.sal_emp partition(p5);

- exchange된 값 확인
select * from hr.exchange_emp;

- 파티션 정보 확인
select partition_name, subpartition_count,high_value, tablespace_name, num_rows,blocks,avg_row_len
from dba_tab_partitions
where table_owner='HR'
and table_name='SAL_EMP';

- partition 이름 변경
alter table hr.sal_emp rename partition p5 to p4;
- 이름 변경 확인
select partition_name, subpartition_count,high_value, tablespace_name, num_rows,blocks,avg_row_len
from dba_tab_partitions
where table_owner='HR'
and table_name='SAL_EMP';

- dump file을 export 받기위한 논리적인 direcotry 확인
select * from dba_directories where directory_name='DATA_PUMP_DIR';

- 물리적으로 export 받기
! expdp system/oracle directory=data_pump_dir tables=hr.sal_emp dumpfile=hr_sal_emp.pump

- 테이블 삭제
drop table hr.sal_emp purge;
- 딕셔너리 정보 확인
select partition_name, subpartition_count,high_value, tablespace_name, num_rows,blocks,avg_row_len
from dba_tab_partitions
where table_owner='HR'
and table_name='SAL_EMP';

- dumpfile import 받기
! impdp system/oracle directory=data_pump_dir tables=hr.sal_emp dumpfile=hr_sal_emp.pump

- 다시 딕셔너리 정보를 조회해보면 복구된걸 확인 할 수 있다.
select partition_name, subpartition_count,high_value, tablespace_name, num_rows,blocks,avg_row_len
from dba_tab_partitions
where table_owner='HR'
and table_name='SAL_EMP';

- 특정 파티션 삭제 후 확인
alter table hr.sal_emp drop partition p4;
select partition_name, subpartition_count,high_value, tablespace_name, num_rows,blocks,avg_row_len
from dba_tab_partitions
where table_owner='HR'
and table_name='SAL_EMP';

- 파티션이 삭제된 상태에서는 dump file에서 해당 파티션의 데이터만 import할 수 있지만, 새로 파티션을 생성한 후에만 가능합니다. 삭제된 파티션의 기준을 모르기 때문에 스크립트를 생성 후 파티션 기준 값 확인
! impdp system/oracle directory=data_pump_dir dumpfile=hr_sal_emp.pump sqlfile=sql_emp.sql content=metadata_only
vi sql_emp.sql

- 기준값을 확인후 파티션 split으로 파티션들 사이에 새로운 파티션 생성
alter table hr.sal_emp split partition pmax at(40000) into(partition p4, partition pmax);
- p4 파티션에 대해서만 import 하기
! impdp system/oracle directory=data_pump_dir dumpfile=hr_sal_emp.pump tables=hr.sal_emp:p4 content=data_only
- 파티션 정보 조회
select partition_name, subpartition_count,high_value, tablespace_name, num_rows,blocks,avg_row_len
from dba_tab_partitions
where table_owner='HR'
and table_name='SAL_EMP';

- p3 파티션 데이터 조회
select * from hr.sal_emp partition(p3)

- p3파티션의 껍질은 남겨놓은채 안의 데이터만 삭제
alter table hr.sal_emp truncate partition p3;

- 내부의 데이터가 없는걸 알 수 있다.
select * from hr.sal_emp partition(p3);

- p3 파티션 껍데기는 존재하기 때문에 바로 p3 data만 import 가능하다.
! impdp system/oracle directory=data_pump_dir dumpfile=hr_sal_emp.pump tables=hr.sal_emp:p3 content=data_only

- import 된 데이터 확인
select * from hr.sal_emp partition(p3);

- sal_emp 테이블의 p4 파티션만 export 받기
! expdp system/oracle directory=data_pump_dir tables=hr.sal_emp:p4 dumpfile=hr_sal_emp_p4.pump

- 생성된 dump file 확인
ls /u01/app/oracle/admin/ORA19C/dpdump/

- p4 파티션 데이터 확인
select * from hr.sal_emp partition(p4);

- p4 파티션 데이터 truncate
alter table hr.sal_emp truncate partition p4;

- 비어있는 데이터 확인
select * from hr.sal_emp partition(p4);

- p4 파티션의 데이터만 import 받기
! impdp system/oracle directory=data_pump_dir dumpfile=hr_sal_emp_p4.pump tables=hr.sal_emp:p4 content=data_only;

- p4 파티션 데이터가 복구되었다.
select * from hr.sal_emp partition(p4);

- 통계정보 확인
select partition_name,high_value, tablespace_name, num_rows,blocks,avg_row_len, to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss')
from dba_tab_partitions
where table_owner='HR'
and table_name='SAL_EMP';

- 파티션까지도 통계수집이 된다.
execute dbms_stats.gather_table_stats('hr','sal_emp');
select partition_name,high_value, tablespace_name, num_rows,blocks,avg_row_len, to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss')
from dba_tab_partitions
where table_owner='HR'
and table_name='SAL_EMP';

- 실제 사용하고 있는 block은 파티션당 19개인데 할당되어있는 block은 1024개로 되어있다.(버그성 의심)
select partition_name, tablespace_name, blocks, bytes from dba_segments where segment_name= 'SAL_EMP';

- 특정 파티션의 통계정보만 삭제
execute dbms_stats.delete_table_stats('hr','sal_emp',partname=>'p4')
select partition_name,high_value, tablespace_name, num_rows,blocks,avg_row_len, to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss')
from dba_tab_partitions
where table_owner='HR'
and table_name='SAL_EMP';

- 특정 파티션의 통계정보만 수집
execute dbms_stats.gather_table_stats('hr','sal_emp',partname=>'p4')
select partition_name,high_value, tablespace_name, num_rows,blocks,avg_row_len, to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss')
from dba_tab_partitions
where table_owner='HR'
and table_name='SAL_EMP';

ARRAYSIZE는 Oracle SQL*Plus에서 한 번에 가져오는 행(row)의 개수를 설정하는 옵션입니다. 값을 크게 하면 한 번에 더 많은 데이터를 가져와 네트워크 왕복 횟수를 줄여 성능을 향상시킬 수 있지만, 클라이언트 메모리 사용이 증가할 수 있습니다.예) 10000건의 데이터를 스캔해야 할때 1000건만 읽어서 운반단위를 채울 수 있다면 10000건을 한꺼번에 다 읽지 않고 1000개씩 10번으로 나누어서 처리할 수 있다.
- 대용량 테이블 생성
drop table hr.sal_emp purge;
create table hr.sal_emp
nologging
as
select rownum as employee_id, last_name, first_name, hire_date, job_id, salary, manager_id, department_id
from hr.employees e, (select level as id from dual connect by level <= 5000);
- 통계정보 확인
select num_rows, blocks, avg_row_len, to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss')
from dba_tables
where owner='HR'
and table_name='SAL_EMP';

- 쿼리문을 fetch는 하되 출력결과는 보여주지 않고 통계정보만 확인
set autotrace trace stat
select * from hr.sal_emp;

Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
39124 consistent gets : 읽은 블록의 수
3706 physical reads
0 redo size
33629855 bytes sent via SQL*Net to client
392712 bytes received via SQL*Net from client
35668 SQL*Net roundtrips to/from client : fetch count 수
0 sorts (memory)
0 sorts (disk)
535000 rows processed : 읽은 행의 수
535000(row) / 35668(fetch count) = 15(한번에 fetch 할수있는 row 수)
테이블이 사용하고 있는 block의 수는 3774개 인데 실제 읽은 block의 수가 39124개로 더 많은 이유는 서버프로세스가 유저 프로세스에게 데이터를 보낼때 15개의 row 밖에 못보내기 때문에 그만큼 같은 block을 중복 i/o 해야 하는 경우가 많아져 consistent gets의 수가 늘어났다.
show arraysize : 서버프로세스가 유저프로세스에게 전달할수 있는 row의 수

- arraysize를 조절 후 쿼리문을 수행하면 consistent gets block i/o가 확실히 줄어들었다.
set arraysize 100
set autotrace trace stat
select * from hr.sal_emp;
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
9022 consistent gets
3706 physical reads
0 redo size
27748357 bytes sent via SQL*Net to client
59225 bytes received via SQL*Net from client
5351 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
535000 rows processed
535000(rows)/5351(fetch count) = 100
- arraysize를 2000으로 설정하면 어느정도 크기 이상부터는 i/o수가 크게 줄어들지는 않는다.
set arraysize 2000
set autotrace trace stat
select * from hr.sal_emp;
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
3975 consistent gets
3706 physical reads
0 redo size
26762449 bytes sent via SQL*Net to client
3323 bytes received via SQL*Net from client
269 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
535000 rows processed
535000(rows)/269(fetch count) = 2000
alter session set statistics_level = all;
select * from hr.sal_emp where salary between 5000 and 8000;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));

show parameter db_file_multiblock_read_count

- ARRAYSIZE와 I/O 수는 밀접한 상관관계를 가집니다. ARRAYSIZE를 크게 설정하면 한 번의 데이터베이스 접근(I/O)으로 더 많은 데이터를 가져오기 때문에 I/O 횟수가 줄어듭니다. 반대로 작게 설정하면 데이터를 여러 번 나누어 가져오기 때문에 I/O 횟수가 증가하게 됩니다.
set arraysize 1000
select * from hr.sal_emp where salary between 5000 and 8000;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));

- arraysize가 일정크기 이상부터는 i/o가 크게 감소되지 않는다.
set arraysize 5000
select * from hr.sal_emp where salary between 5000 and 8000;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));

- 대용량 데이터를 인덱스 스캔을 하게되면 full table scan보다 많은 i/o를 유발한다.
create index hr.sal_emp_idx on hr.sal_emp(salary);
set arraysize 1000
select /*+ index(s sal_emp_idx) */ * from hr.sal_emp s where salary between 5000 and 8000;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));

- 기존 생성되어있는 테이블에 파티션 설정
alter table hr.sal_emp
modify
partition by range(salary)
(partition p1 values less than(5000),
partition p2 values less than(10000),
partition p3 values less than(30000),
partition pmax values less than(maxvalue));
- 통계수집
execute dbms_stats.gather_table_stats('hr','sal_emp');
- 파티션 통계정보 확인
select partition_name,high_value, tablespace_name, num_rows,blocks,avg_row_len, to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss')
from dba_tab_partitions
where table_owner='HR'
and table_name='SAL_EMP';

- partition pruning 기능이 작동되어 full table scan을 하더라도 특정 파티션만 scan 하기 때문에 i/o가 현저히 줄었다.
set arraysize 1000
select * from hr.sal_emp s where salary between 5000 and 8000;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));

- allstats last partition : 파티션 정보까지 같이 실행계획에 나타냄
select * from hr.sal_emp s where salary between 5000 and 8000;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last partition'));

- salary의 범위를 5000~11000까지 하게 되면 2개의 파티션을 읽게 된다.
select * from hr.sal_emp s where salary between 5000 and 11000;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last partition'));

select * from hr.sal_emp s where salary between 5000 and 11000;- 바인드 변수로 조회한다고 해서 i/o 성능이 떨어지지는 않는다.
variable b_start number
variable b_stop number
execute :b_start := 5000
execute :b_stop := 8000
select * from hr.sal_emp s where salary between :b_start and :b_stop;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last partition'));

prefixed : 파티션 인덱스를 생성할때 파티션 키 컬럼을 인덱스 키 컬럼 왼쪽 선두에 두는것을 의미 noprefixed : 파티션 인덱스를 생성할때 파티션 키 컬럼을 인덱스 키 컬럼 왼쪽 선두에 두지 않는 것을 의미- 테이블 생성
create table hr.emp_local
partition by range(employee_id)
(partition p1 values less than(20000),
partition p2 values less than(40000),
partition p3 values less than(80000),
partition p4 values less than(100000),
partition p5 values less than(120000),
partition pmax values less than(maxvalue))
as
select rownum as employee_id, last_name, first_name, hire_date, job_id, salary, manager_id, department_id
from hr.employees e, (select level as id from dual connect by level <= 1000);
- 통계수집
execute dbms_stats.gather_table_stats('hr','emp_local');
- 파티션 통계정보 확인
select partition_position,partition_name,high_value, tablespace_name, num_rows,blocks,avg_row_len, to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss')
from dba_tab_partitions
where table_owner='HR'
and table_name='EMP_LOCAL';

- 1번 파티션을 사용해서 조회한다.
select * from hr.emp_local where employee_id = 1000;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last partition'));

- 범위가 넒어 여러개의 파티션을 읽어야 하기 때문에 iterator으로 실행되었다.
select count(*) from hr.emp_local where employee_id between 1000 and 25000;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last partition'));

- local 인덱스 생성
create unique index hr.emp_local_idx on hr.emp_local(employee_id) local;
- 생성 인덱스 정보 확인
select i.index_name, i.uniqueness, p.locality, p.alignment, i.partitioned, p.partition_count
from dba_indexes i, dba_part_indexes p
where i.table_name = 'EMP_LOCAL'
and i.owner = 'HR'
and p.table_name = i.table_name
and p.index_name = i.index_name;

- index unique scan을 통해 i/o가 획기적으로 줄었다.
select * from hr.emp_local where employee_id = 1000;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last partition'));

- 기존 full table scan 보다 index range scan이 i/o가 훨씬 줄었다.
select /*+ index(e emp_local_idx) */ count(*) from hr.emp_local e where employee_id between 1000 and 25000;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last partition'));

- 인덱스의 파티션 설정 확인
select index_name, partition_name
from dba_ind_partitions
where index_name = 'EMP_LOCAL_IDX';

- 테이블 생성
create table hr.emp_global
partition by range(employee_id)
(partition p1 values less than(20000),
partition p2 values less than(40000),
partition p3 values less than(80000),
partition p4 values less than(100000),
partition p5 values less than(120000),
partition pmax values less than(maxvalue))
as
select rownum as employee_id, last_name, first_name, hire_date, job_id, salary, manager_id, department_id
from hr.employees e, (select level as id from dual connect by level <= 1000);
- 통계수집
execute dbms_stats.gather_table_stats('hr','emp_global');
- 파티션 통계정보 확인
select partition_position,partition_name,high_value, tablespace_name, num_rows,blocks,avg_row_len, to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss')
from dba_tab_partitions
where table_owner='HR'
and table_name='EMP_GLOBAL';

- global 인덱스 생성
create index hr.emp_global_idx on hr.emp_global(hire_date) global
partition by range(hire_date)
(partition p2004 values less than(to_date('2005-01-01','yyyy-mm-dd')),
partition p2005 values less than(to_date('2006-01-01','yyyy-mm-dd')),
partition p2006 values less than(to_date('2007-01-01','yyyy-mm-dd')),
partition pmax values less than(maxvalue));
- 인덱스의 파티션 설정 확인
select index_name, partition_name,high_value,blevel, leaf_blocks, num_rows,clustering_factor, to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss'),pct_free
from dba_ind_partitions
where index_name = 'EMP_GLOBAL_IDX';

- 테이블 파티션은 6개 이지만 인덱스 파티션은 4개이다.
select i.index_name, i.uniqueness, p.locality, p.alignment, i.partitioned, p.partition_count
from dba_indexes i, dba_part_indexes p
where i.table_name = 'EMP_GLOBAL'
and i.owner = 'HR'
and p.table_name = i.table_name
and p.index_name = i.index_name;

- employee_id 에는 인덱스가 설정되어 있지 않아 full table scan을 실행하였다.
select * from hr.emp_global where employee_id = 100;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last partition'));

- 조건을 인덱스가 설정된 hire_date 컬럼을 이용하여 index scan을 유도하였다.
select /*+ index(e emp_global_idx) */ * from hr.emp_global e where hire_date >= to_date('2001-01-01','yyyy-mm-dd') and hire_date < to_date('2002-01-01','yyyy-mm-dd');
select * from table(dbms_xplan.display_cursor(null,null,'allstats last partition'));

- 건수를 조회할 때, INDEX FAST FULL SCAN은 전체 인덱스 블록을 멀티 블록 I/O 방식으로 읽고, 그 중에서 조건에 맞는 데이터를 찾아 처리합니다.
select count(*) from hr.emp_global e where hire_date >= to_date('2001-01-01','yyyy-mm-dd') and hire_date < to_date('2002-01-01','yyyy-mm-dd');
select * from table(dbms_xplan.display_cursor(null,null,'allstats last partition'));

- 조건절의 컬럼이 파티션된 인덱스를 사용하면, INDEX RANGE SCAN이 건수를 셀 때 더 나은 I/O 성능을 제공할 수 있어, INDEX FAST FULL SCAN이 항상 좋은 선택은 아니다.
select /*+ index_rs(e emp_global_idx) */ count(*) from hr.emp_global e where hire_date >= to_date('2001-01-01','yyyy-mm-dd') and hire_date < to_date('2002-01-01','yyyy-mm-dd');
select * from table(dbms_xplan.display_cursor(null,null,'allstats last partition'));

- 테이블의 파티션 정보 확인
select partition_position,partition_name,high_value, tablespace_name, num_rows,blocks,avg_row_len, to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss')
from dba_tab_partitions
where table_owner='HR'
and table_name='EMP_GLOBAL';

- 인덱스의 파티션 정보 확인
select index_name, partition_name,high_value,blevel, leaf_blocks, num_rows,clustering_factor, to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss'),pct_free,status
from dba_ind_partitions
where index_name = 'EMP_GLOBAL_IDX';

- 테이블 파티션을 삭제하면 해당 데이터과 연결되어있던 global index들은 unusable 상태로 변경된다.
alter table hr.emp_global drop partition p4;
select index_name, partition_name,high_value,blevel, leaf_blocks, num_rows,clustering_factor, to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss'),pct_free,status
from dba_ind_partitions
where index_name = 'EMP_GLOBAL_IDX';

- 인덱스가 unusable 상태이면 인데스를 이용한 scan이 불가능하기 때문에 오류가 발생한다.
select /*+ index_rs(e emp_global_idx) */ count(*) from hr.emp_global e where hire_date >= to_date('2001-01-01','yyyy-mm-dd') and hire_date < to_date('2002-01-01','yyyy-mm-dd');

- unusable 상태가 된 인덱스는 다시 rebuild 해줘야 한다.
alter index hr.emp_global_idx rebuild partition p2004;
alter index hr.emp_global_idx rebuild partition p2005;
alter index hr.emp_global_idx rebuild partition p2006;
alter index hr.emp_global_idx rebuild partition pmax;
- 다시 인덱스 파티션 정보를 조회해보면 usable로 변경되었다.
select index_name, partition_name,high_value,blevel, leaf_blocks, num_rows,clustering_factor, to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss'),pct_free,status
from dba_ind_partitions
where index_name = 'EMP_GLOBAL_IDX';

- global 인덱스에 대해 split 하게 되어도 상태에는 아무런 문제가 되지 않는다.
alter index hr.emp_global_idx split partition pmax at(to_date('2008-01-01','yyyy-mm-dd')) into (partition p2007, partition pmax);
select index_name, partition_name,high_value,blevel, leaf_blocks, num_rows,clustering_factor, to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss'),pct_free,status
from dba_ind_partitions
where index_name = 'EMP_GLOBAL_IDX';

- 기존 p2007 인덱스가 바라보던 데이터들은 pmax 인덱스로 넘어가기 때문에 unusable 상태로 변경되었다.
alter index hr.emp_global_idx drop partition p2007;
select index_name, partition_name,high_value,blevel, leaf_blocks, num_rows,clustering_factor, to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss'),pct_free,status
from dba_ind_partitions
where index_name = 'EMP_GLOBAL_IDX';

alter index hr.emp_global_idx rebuild partition pmax;