ITPub博客

首页 > 数据库 > Oracle > dbms_pclxutil.build_part_index包的用法

dbms_pclxutil.build_part_index包的用法

原创 Oracle 作者:水逸冰 时间:2019-01-12 15:12:44 0 删除 编辑

dbms_pclxutil.build_part_index包可以用来以并行的方式rebuild local index。
包的来源文件是$ORACLE_HOME/rdbms/admin/dbmspclx.sql

该sql文件中可以看到包的用法:
procedure build_part_index (
     jobs_per_batch in number default 1,
     procs_per_job  in number default 1,
     tab_name       in varchar2 default null,
     idx_name       in varchar2 default null,
     force_opt      in boolean default FALSE);
  --
  -- jobs_per_batch: #jobs to be created (1 <= job_count <= #partitions)
  --
  -- procs_per_job:  #slaves per job (1 <= degree <= max_slaves)
  --
  -- tab_name:       name of the partitioned table (an exception is
  --                 raised if the table does not exist or not
  --                 partitioned)
  --
  -- idx_name:       name given to the local index (an exception is
  --                 raised if a local index is not created on the
  --                 table tab_name)
  --
  -- force_opt:      if TRUE force rebuild of all partitioned indices;
  --                 otherwise rebuild only the partitions marked
  --                 'UNUSABLE'
  --

该包中只有这一个存储过程
SQL> desc dbms_pclxutil
PROCEDURE BUILD_PART_INDEX
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 JOBS_PER_BATCH                 NUMBER                  IN     DEFAULT
 PROCS_PER_JOB                  NUMBER                  IN     DEFAULT
 TAB_NAME                       VARCHAR2                IN     DEFAULT
 IDX_NAME                       VARCHAR2                IN     DEFAULT
 FORCE_OPT                      BOOLEAN                 IN     DEFAULT
 
以如下语句为例,含义是每次job处理3个分区,每次处理的并行数为2。目标索引为DAY_PART的T_DAY_PART。TRUE代表local index全部rebuild,相应地FALSE代表只rebuild unusable的local index。
exec dbms_pclxutil.build_part_index(3, 2, 'DAY_PART', 'T_DAY_PART', TRUE);

通过10046可以看到递归sql
select toid from type$ where package_obj#=:1 and typ_name=:2
select oid$ from oid$ where obj#=:1
select name,password,datats#,tempts#,type#,defrole,resource$, ptime, decode(defschclass,NULL,'DEFAULT_CONSUMER_GROUP
',defschclass), spare1,spare4,ext_username,spare2,nvl(spare3,16382),spare9,spare10 from user$ where user#=:1
select obj#,type#,ctime,mtime,stime, status, dataobj#, flags, oid$, spare1, spare2, spare3, signature, spare7, spare
8, spare9, nvl(dflcollid, 16382), creappid, creverid, modappid, modverid, crepatchid, modpatchid from obj$ where own
er#=:1 and name=:2 and namespace=:3 and remoteowner is null and linkname is null and subname is null
select obj#, prgoid, creation_time, mod_time, spec_time, flags    from sys.scheduler$_lwjob_obj where userid = :1 an
d name = :2 and    subname is null
select o.owner#,o.name,o.namespace,o.remoteowner,o.linkname,o.subname from obj$ o where o.obj#=:1
insert into sys.scheduler$_job (program_oid, schedule_expr, schedule_id, queue_owner, queue_name, queue_agent, event
_rule, mxdur_msgid, last_enabled_time, class_oid, next_run_date, last_start_date, last_end_date, retry_count, run_co
unt, failure_count, running_instance, running_slave, flags, job_status, creator, client_id, guid, char_env, start_da
te, end_date, instance_id, fw_name, fw_oid, destination, credential_name, credential_owner, credential_oid, dest_oid
, job_dest_id, run_invoker, connect_credential_name, connect_credential_owner, connect_credential_oid, program_actio
n, schedule_limit, priority, job_weight, number_of_args, max_runs, max_failures, max_run_duration, comments, user_ca
llback, user_callback_ctx, nls_env, source, env, database_role, owner_udn, dist_flags, pdb_id, obj#) values (:1, :2,
 :3, :4, :5, :6, :7, :8, :9, :10, :11, :12, :13, :14, :15, :16, :17, :18, :19, :20, :21, :22, :23, :24, :25, :26, :2
7, :28, :29, :30, :31, :32, :33, :34, :35, :36, :37, :38, :39, :40, :41, :42, :43, :44, :45, :46, :47, :48, :49, :50
, :51, :52, :53, :54, :55, :56, :57, :58)
delete from dependency$ where d_obj#=:1
delete from access$ where d_obj#=:1
insert into access$(d_obj#,order#,columns,types) values (:1,:2,:3,:4)
insert into obj$(owner#,name,namespace,obj#,type#,ctime,mtime,stime,status,remoteowner,linkname,subname,dataobj#,fla
gs,oid$,spare1,spare2,spare3, signature, spare7, spare8, spare9, dflcollid, creappid, creverid, modappid, modverid,
crepatchid, modpatchid) values(:1,:2,:3,:4,:5,:6,:7,:8,:9,:10,:11,:12,:13,:14,:15,:16,:17,:18, :19,:20,:21,:22,decod
e(:23,0,null,:23),:24,:25,:26,:27,:28,:29)
select userid, name, subname, flags    from sys.scheduler$_lwjob_obj where obj# = :1
update sys.scheduler$_job set  last_enabled_time = :1, retry_count = :2, run_count = :3, failure_count = :4, job_sta
tus = :5 where  obj# = :6
insert into access$(d_obj#,order#,columns,types) values (:1,:2,:3,:4)
update obj$ set obj#=:4, type#=:5,ctime=:6,mtime=:7,stime=:8,status=:9,dataobj#=:10,flags=:11,oid$=:12,spare1=:13,sp
are2=:14,spare3=:15,signature=:16,spare7=:17,spare8=:18,spare9=:19, dflcollid=decode(:20,0,null,:20),creappid=:21,cr
everid=:22, modappid=:23,modverid=:24,crepatchid=:25,modpatchid=:26 where owner#=:1 and name=:2 and namespace=:3 and
 remoteowner is null and linkname is null and subname is null
insert into access$(d_obj#,order#,columns,types) values (:1,:2,:3,:4)
insert into access$(d_obj#,order#,columns,types) values (:1,:2,:3,:4)
insert into access$(d_obj#,order#,columns,types) values (:1,:2,:3,:4)
insert into access$(d_obj#,order#,columns,types) values (:1,:2,:3,:4)
insert into access$(d_obj#,order#,columns,types) values (:1,:2,:3,:4)
insert into access$(d_obj#,order#,columns,types) values (:1,:2,:3,:4)

可以看到上述过程没有加锁,所以猜测该dbms包在rebuild local index的过程中,无法处理open transaction。
实验验证
MING@ming(MING)> SELECT   PARTITION_NAME, INDEX_NAME,STATUS FROM USER_IND_PARTITIONS WHERE   INDEX_NAME IN ('ID_DAY_PART','T_DAY_PART');

PARTITION_NAME                 INDEX_NAME                STATUS
------------------------------ ------------------------- --------
P1                             ID_DAY_PART               USABLE
SYS_P420                       ID_DAY_PART               UNUSABLE
SYS_P421                       ID_DAY_PART               UNUSABLE
SYS_P422                       ID_DAY_PART               UNUSABLE

MING@ming(MING)> select * from DAY_PART partition(SYS_P422);

        ID EITIME
---------- ------------
         2 15-JAN-19

MING@ming(MING)> select * from DAY_PART partition(SYS_P421);

        ID EITIME
---------- ------------
         2 10-JAN-19

MING@ming(MING)> select * from DAY_PART partition(SYS_P420);

        ID EITIME
---------- ------------
         1 05-JAN-19
         2 05-JAN-19

MING@ming(MING)> select * from DAY_PART partition(p1);      

no rows selected

新开会话,不提交
MING@ming(MING)>  update day_part set id=10000  where id=1;

1 row updated.

MING@ming(MING)> exec dbms_pclxutil.build_part_index(3, 2, 'DAY_PART', 'ID_DAY_PART', TRUE);                        
PL/SQL procedure successfully completed.

MING@ming(MING)> SELECT   PARTITION_NAME, INDEX_NAME,STATUS FROM USER_IND_PARTITIONS WHERE   INDEX_NAME IN ('ID_DAY_PART','T_DAY_PART');

PARTITION_NAME                 INDEX_NAME                STATUS
------------------------------ ------------------------- --------
P1                             ID_DAY_PART               USABLE
SYS_P420                       ID_DAY_PART               UNUSABLE
SYS_P421                       ID_DAY_PART               USABLE
SYS_P422                       ID_DAY_PART               USABLE
SYS_P420分区索引还是unusable。
SQL> select * from dba_scheduler_running_jobs;

no rows selected
后台也没有正在运行的job,所以open transaction不会处理了。


新建一张分区表
INDEX_NAME                     STATUS
------------------------------ --------
ID_DAY_PART                    UNUSABLE
ID_DAY_PART                    UNUSABLE
ID_DAY_PART                    UNUSABLE

SQL> SELECT COUNT(*) FROM DAY_PART PARTITION(SYS_P3953);

  COUNT(*)
----------
   2000000

SQL> SELECT COUNT(*) FROM DAY_PART PARTITION(SYS_P4053);

  COUNT(*)
----------
   2000000

利用包重建索引
SQL> exec dbms_pclxutil.build_part_index(3, 2, 'DAY_PART', 'ID_DAY_PART', TRUE);

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.02
SQL> SELECT INDEX_NAME,STATUS FROM DBA_IND_PARTITIONS WHERE INDEX_NAME='ID_DAY_PART';

INDEX_NAME                     STATUS
------------------------------ --------
ID_DAY_PART                    USABLE
ID_DAY_PART                    UNUSABLE
ID_DAY_PART                    UNUSABLE

Elapsed: 00:00:00.00
SQL> SELECT INDEX_NAME,STATUS FROM DBA_IND_PARTITIONS WHERE INDEX_NAME='ID_DAY_PART';

INDEX_NAME                     STATUS
------------------------------ --------
ID_DAY_PART                    USABLE
ID_DAY_PART                    UNUSABLE
ID_DAY_PART                    UNUSABLE

Elapsed: 00:00:00.00
SQL> SELECT INDEX_NAME,STATUS FROM DBA_IND_PARTITIONS WHERE INDEX_NAME='ID_DAY_PART';

INDEX_NAME                     STATUS
------------------------------ --------
ID_DAY_PART                    USABLE
ID_DAY_PART                    UNUSABLE
ID_DAY_PART                    USABLE

Elapsed: 00:00:00.00
SQL> SELECT INDEX_NAME,STATUS FROM DBA_IND_PARTITIONS WHERE INDEX_NAME='ID_DAY_PART';

INDEX_NAME                     STATUS
------------------------------ --------
ID_DAY_PART                    USABLE
ID_DAY_PART                    USABLE
ID_DAY_PART                    USABLE

Elapsed: 00:00:00.00
虽然包马上返回了结果,但是索引并没有马上重建完成,说明包的作用只是建立一个重建索引的job,job创建成功就返回,不管索引是否重建成功。

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/31480688/viewspace-2383043/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
精通oracle,mysql和linux,热衷于研究数据库,擅长shell和Python自动化运维。VX:18302174682

注册时间:2017-08-05

  • 博文量
    117
  • 访问量
    188656