Global index PK改造local index PK

Posted nathon-wang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Global index PK改造local index PK相关的知识,希望对你有一定的参考价值。

创建测试表:
=====================================================================================================
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不成功,索引应该会回滚。

 

























































































































以上是关于Global index PK改造local index PK的主要内容,如果未能解决你的问题,请参考以下文章

[Partition][Index]对于Partition表而言,是否Global Index 和 Local Index 可以针对同一个字段建立?

如果 OpenType 中的 Local 和 Global Subr INDEX 基本上是可重用的组件

oracle11.2中分区功能测试之add&amp;split partition对global&amp;local index的影响

SwiftUI 后台刷新多个 Section 导致 global index in collection view 与实际不匹配问题的解决

SwiftUI 后台刷新多个 Section 导致 global index in collection view 与实际不匹配问题的解决

读点论文Focal Self-attention for Local-Global Interactions in Vision Transformers局部和全局注意力进行交互实现新SOTA