Oracle -当我使用重命名执行CTAS时,是否必须删除并重建索引

snvhrwxg  于 2023-06-05  发布在  Oracle
关注(0)|答案(2)|浏览(103)

我有一个非常大的表(超过50亿条记录),而不是执行更新语句,甚至运行pl/sql bill collect/forall,我选择在select中执行更新的CTAS。我只是简单地填充一个日期字段与sysdate如果它是空的。
创建NEW表后,我将重命名OLD表,并将NEW表重命名为OLD表的原始名称。
我将在删除OLD表之前比较记录计数和其他验证。
我的问题是,如果旧表的日期列上有一个索引,我是否必须删除该索引并重新创建它才能在现在具有旧表名称的新表上正常工作?

w9apscun

w9apscun1#

最好用更新的数据创建一个分区表,然后使用“alter table exchange partition”,这样就可以避免赠款带来的问题。然后您可以重建所有索引。
简单的例子:https://dbfiddle.uk/ynZG8lGh

-- our test table T:
create table t as
  select level a
        ,decode(mod(level,2),1,date'2020-01-01',sysdate) dt
  from dual
  connect by level<=1e4;
create index t_ix on t(dt);
alter table t add constraint t_pk primary key (a);

-- creating a temporary partitioned table with the updated data as we need:
create table t_new(
  a number primary key,
  dt date
)
  partition by range(a)
    (partition p1 values less than (maxvalue))
;
-- parallel direct insert from the old table:
insert/*+ append enable_parallel_dml parallel(8) */ into t_new 
  select a, nvl(dt,sysdate) dt from t;

-- switching tables' data:
alter table t_new exchange partition p1 with table t;
-- checking indexes on T: as you can see all of them in in the UNUSABLE status:
select index_name,status from user_indexes where table_name='T';

-- rebuilding them in parallel and then switching them to noparallel:
begin
  for r in (
    select index_name 
    from user_indexes
    where table_name='T' 
    and status='UNUSABLE'
  )
  loop
    execute immediate 'alter index '||r.index_name||' rebuild parallel 8';
    execute immediate 'alter index '||r.index_name||' noparallel';
  end loop;
end;
/
--checking their statuses again: now they're valid:
select index_name,status from user_indexes where table_name='T';
nx7onnlm

nx7onnlm2#

是的,您必须在新建的表上创建索引。新表最终获得与旧表相同的名称,这一事实在Oracle字典中不会以任何方式将它们关联起来。它们是完全独立的对象。
如果希望新表上的索引具有相同的名称,则必须首先从旧表中删除旧索引。或者,您可以使用新名称创建新索引,然后在进行表名交换时重命名两个索引以交换它们的名称。但是在进行这种维护时,通常没有理由在旧表上保留索引,因为该表将继续存在(如果有的话),只是作为备份。因此,只需将索引放在它上面,这样就可以在新表上创建一个同名的索引。在表重命名之前或之后创建新表的索引也没有关系。
像您这样大的表肯定应该分区。关于你的索引的几点注意事项。在Exadata中,我们几乎从不索引日期列,因为智能扫描消除了这样做的需要,并且日期查找几乎从不高频。在常规Oracle中,可能仍然需要它们,但以下是一些注意事项:
如果分区与索引位于 same date列上,则索引应为LOCAL。您可以一次构建所有分区,也可以先将其创建为UNUSABLE,然后单独重建每个分区,以最大限度地减少临时空间需求并优化PX分布。但是,如果查询要求“lastest month”或“year 2022”,并且您按月份对该日期进行分区,您不希望该索引全部存在,它只会碍事。分区修剪将更好地服务于这样的查询。索引日期列(也是分区键)的唯一原因是,如果您有请求非常小的切片的查询(例如一个小时或至多一天)。如果不是这种情况,请关闭索引并允许分区修剪,以有效地完成索引的目的。
如果索引位于 different 日期列(不是分区键)上,您可能仍然希望将其设置为LOCAL以简化分区维护,只要您没有高频率的查询(例如:每隔几分钟)请求非常新的数据而不进行分区修剪(因为索引的每个分区将需要针对每个值查找的查找)。如果您的查询频率相对较低,或者需要更大的数据,则本地索引的好处远远超过GLOBAL索引的性能好处。

相关问题