创建测试表:
=====================================================================================================
create table TEST_TAB1 (
start_date DATE,
store_id NUMBER
)
PARTITION BY RANGE (start_date)
(
PARTITION TEST_TAB_p1 VALUES LESS THAN (TO_DATE('1-2-2020', 'DD-MM-YYYY')),
PARTITION TEST_TAB_p2 VALUES LESS THAN (TO_DATE('1-3-2020', 'DD-MM-YYYY')),
PARTITION TEST_TAB_p3 VALUES LESS THAN (TO_DATE('1-4-2020', 'DD-MM-YYYY')),
PARTITION TEST_TAB_p4 VALUES LESS THAN (TO_DATE('1-5-2020', 'DD-MM-YYYY')),
PARTITION TEST_TAB_p5 VALUES LESS THAN (TO_DATE('1-6-2020', 'DD-MM-YYYY')),
PARTITION TEST_TAB_p6 VALUES LESS THAN (TO_DATE('1-7-2020', 'DD-MM-YYYY'))
);
创建主键:
=====================================================================================================
SQL> CREATE UNIQUE INDEX PK_IDX_TAB1 on TEST_TAB1(store_id);
SQL> ALTER TABLE TEST.TEST_TAB1 ADD CONSTRAINT PK_IDX_TAB1 PRIMARY KEY (store_id) USING INDEX PK_IDX_TAB1;
set lines 200 pages 2000
col index_name for a30
col table_name for a30
select index_name,table_name,UNIQUENESS,GLOBAL_STATS from dba_indexes where index_name = 'PK_IDX_TAB1';
INDEX_NAME TABLE_NAME UNIQUENESS GLOBAL_ST
------------------------------ ------------------------------ --------------------------- ---------
PK_IDX_TAB1 TEST_TAB1 UNIQUE YES
插入数据:
=====================================================================================================
insert into TEST_TAB1 values ( '15-Jan-20', 2);
commit;
insert into TEST_TAB1 values ( '15-Feb-20', 2);
insert into TEST_TAB1 values ( '15-Mar-20', 2);
TEST @testdb> insert into TEST_TAB1 values ( '15-Jan-20', 2);
commit;
1 row created.
TEST @testdb>
Commit complete.
TEST @testdb> insert into TEST_TAB1 values ( '15-Feb-20', 2);
insert into TEST_TAB1 values ( '15-Feb-20', 2)
*
ERROR at line 1:
ORA-00001: unique constraint (TEST.PK_IDX_TAB1) violated
把索引换成本地的:
=====================================================================================================
alter table TEST_TAB1 drop primary key drop index;
CREATE UNIQUE INDEX PK_IDX_TAB1 on TEST_TAB1(store_id) local;
ERROR at line 1:
ORA-14039: partitioning columns must form a subset of key columns of a UNIQUE index
CREATE UNIQUE INDEX PK_IDX_TAB1 on TEST_TAB1(start_date,store_id) local; (这样创建索引会使逻辑发生改变,想保证store_id的全局唯一性,这样就不可取)
ALTER TABLE TEST.TEST_TAB1 ADD CONSTRAINT PK_IDX_TAB1 PRIMARY KEY (start_date,store_id) USING INDEX PK_IDX_TAB1;
INDEX_NAME TABLE_NAME UNIQUENESS GLOBAL_ST
------------------------------ ------------------------------ --------------------------- ---------
PK_IDX_TAB1 TEST_TAB1 UNIQUE NO
CONSTRAINT_NAME CON TABLE_NAME INDEX_NAME
------------------------------ --- ------------------------------ ------------------------------
PK_IDX_TAB1 P TEST_TAB1 PK_IDX_TAB1
如果主键中带有了分区键,不同分区中的分区键本身就是不同的,只要在分区内保证其他列唯一即可。 即使不同分区间的其他列有相同的值,因为分区键不同,该行数据在全局上也是唯一的。
如果主键中不带分区键,在创建索引的时必须加入分区键,否则就会报错。如果加入了分区键,本身unique逻辑就会发生改变。
结论:
=====================================================================================================
如果主键中带有分区键,可以将全局索引改造成local的分区索引,保证全局的唯一性。
如果主键中不带分区键,主键索引必须使用Global,无法将全局索引改造成local的分区索引。
为了解决索引分裂,改造local hash分区或者 reverse分区:
========================================
alter table TEST_TAB1 drop primary key drop index;
CREATE UNIQUE INDEX PK_IDX_TAB1 on TEST_TAB1(start_date,store_id) local partition by hash(store_id) online;
TEST @testdb> CREATE UNIQUE INDEX PK_IDX_TAB1 on TEST_TAB1(start_date,store_id) local partition by hash(store_id) online;
CREATE UNIQUE INDEX PK_IDX_TAB1 on TEST_TAB1(start_date,store_id) local partition by hash(store_id) online *
ERROR at line 1:
ORA-02158: invalid CREATE INDEX option
CREATE UNIQUE INDEX PK_IDX_TAB1 on TEST_TAB1(start_date,store_id) reverse local online;
truncate分区并update Global索引过程中杀掉会话测试:
================================================================
create table TEST_TAB1 (
start_date DATE,
store_id NUMBER
)
PARTITION BY RANGE (start_date)
(
PARTITION TEST_TAB_p1 VALUES LESS THAN (TO_DATE('1-2-2020', 'DD-MM-YYYY')),
PARTITION TEST_TAB_p2 VALUES LESS THAN (TO_DATE('1-3-2020', 'DD-MM-YYYY')),
PARTITION TEST_TAB_p3 VALUES LESS THAN (TO_DATE('1-4-2020', 'DD-MM-YYYY')),
PARTITION TEST_TAB_p4 VALUES LESS THAN (TO_DATE('1-5-2020', 'DD-MM-YYYY')),
PARTITION TEST_TAB_p5 VALUES LESS THAN (TO_DATE('1-6-2020', 'DD-MM-YYYY')),
PARTITION TEST_TAB_p6 VALUES LESS THAN (TO_DATE('1-7-2020', 'DD-MM-YYYY'))
);
CREATE UNIQUE INDEX PK_IDX_TAB1 on TEST_TAB1(start_date,store_id);
ALTER TABLE TEST.TEST_TAB1 ADD CONSTRAINT PK_IDX_TAB1 PRIMARY KEY (start_date,store_id) USING INDEX PK_IDX_TAB1;
set lines 200 pages 2000
col index_name for a30
col table_name for a30
select index_name,table_name,UNIQUENESS,status,GLOBAL_STATS from dba_indexes where index_name = 'PK_IDX_TAB1';
INDEX_NAME TABLE_NAME UNIQUENESS STATUS GLOBAL_ST
------------------------------ ------------------------------ --------------------------- ------------------------ ---------
PK_IDX_TAB1 TEST_TAB1 UNIQUE VALID YES
begin
for i in 1 .. 500000 loop
insert into TEST_TAB1 values ( '15-Feb-20', i);
end loop;
commit;
end;
/
begin
for i in 500001 .. 1000000 loop
insert into TEST_TAB1 values ( '15-Feb-20', i);
end loop;
commit;
end;
/
begin
for i in 1000001 .. 2000000 loop
insert into TEST_TAB1 values ( '15-Feb-20', i);
end loop;
commit;
end;
/
TEST @testdb> select start_date,count(*) from TEST_TAB1 group by start_date;
START_DATE COUNT(*)
------------------ ----------
15-JAN-20 1
15-FEB-20 2000000
TEST @testdb> select sid from v$mystat where rownum < 2;
SID
----------
2277
TEST @testdb> select spid from v$process where addr = (select paddr from v$session where sid=2277);
SPID
------------------------------------------------------------------------
14096
TEST @testdb> !ps -ef | grep 14096
oracle 14096 14030 0 11:33 ? 00:00:00 oracletestdb (DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq)))
alter table TEST_TAB1 truncate partition TEST_TAB_p2 update indexes;
杀进程
TEST @testdb> alter table TEST_TAB1 truncate partition TEST_TAB_p2 update indexes;
alter table TEST_TAB1 truncate partition TEST_TAB_p2 update indexes
*
ERROR at line 1:
ORA-03113: end-of-file on communication channel
Process ID: 14096
Session ID: 2277 Serial number: 271
INDEX_NAME TABLE_NAME UNIQUENESS STATUS GLOBAL_ST
------------------------------ ------------------------------ --------------------------- ------------------------ ---------
PK_IDX_TAB1 TEST_TAB1 UNIQUE VALID YES
START_DATE COUNT(*)
------------------ ----------
15-JAN-20 1
15-FEB-20 2000000
结论: 杀掉truncate的session, truncate不成功,索引应该会回滚。