استفاده از عبارت parallel در زمان ساخت primary key منجر به انجام عملیات به صورت همروند نخواهد شد. دستور زیر را مشاهده کنید:
SQL> alter table all_table add constraint pk_1 primary key (id) parallel 10; Table altered. Elapsed: 00:00:12.36
با فعال کردن trace خواهیم دید که اوراکل برای ساخت ایندکس متناظر با این PK، از عبارت noparallel استفاده کرده و عبارت parallel تاثیر مثبتی در زمان ایجاد این Primary Key نداشته است:
PARSING IN CURSOR #140396268419760 len=72 dep=1 uid=109 oct=9 lid=109 tim=29571676036680 hv=2994446983 ad='b9930010' sqlid='c1ddax6t7r8n7' CREATE UNIQUE INDEX "USEF"."PK_1" on "USEF"."ALL_TABLE"("ID") NOPARALLEL
بنابرین زمان اجرای دستور فوق با دستور زیر برابر خواهد بود و اجرای هر دو دستور به 13 ثانیه زمان نیاز دارد:
SQL> alter table all_table add constraint pk_1 primary key (id) noparallel; Table altered. Elapsed: 00:00:12.95
برای کاهش این زمان، به عنوان یک راهکار می توان قبل از ساخت Primary Key، ایندکس unique مربوط به آن را در حالت parallel ایجاد کرد و سپس محدودیت PK را اضافه کرد:
SQL> CREATE UNIQUE INDEX PK_1 on ALL_TABLE(ID) parallel 10; Index created. Elapsed: 00:00:02.45 SQL> alter table all_table add constraint pk_1 primary key (id) using index PK_1; Table altered. Elapsed: 00:00:03.90
با این ترقند، 13 ثانیه را به 6 ثانیه کاهش داده ایم البته اضافه کردن Primary Key به تنهایی به چهار ثانیه زمان نیاز خواهد داشت چرا که قبل از اضافه شدن constraint باید از not null بودن ستون مطمئن شد بنابرین اگر محدودیت not null روی این ستون موجود باشد، این زمان بسیار کاهش پیدا خواهد کرد:
SQL> alter table all_table drop constraint pk_1; Table altered. SQL> alter table all_table modify id not null; Table altered. Elapsed: 00:00:03.85 SQL> alter table all_table add constraint pk_1 primary key (id) using index PK_1; Table altered. Elapsed: 00:00:00.01
ساخت Foreign Key
قصد داریم بین جدول tb_child و all_table به صورت زیر Foreign Key ایجاد کنیم:
SQL> ALTER TABLE tb_child ADD CONSTRAINT fk_1 FOREIGN KEY (id_fk) REFERENCES all_table(id) ; Table altered. Elapsed: 00:01:06.94
ایجاد Foreign Key حدودا 1 دقیقه به طول انجامید.
همروندی را در سطح session و table فعال کرده و مجددا این کار را تکرار می کنیم:
SQL> alter table tb_child drop constraint fk_1; Table altered. SQL> ALTER SESSION FORCE PARALLEL DDL PARALLEL 10; Session altered. SQL> ALTER SESSION FORCE PARALLEL QUERY PARALLEL 10; Session altered. SQL> ALTER TABLE TB_CHILD PARALLEL 10; Table altered. SQL> ALTER TABLE tb_child ADD CONSTRAINT fk_1 FOREIGN KEY (id_fk) REFERENCES all_table(id) ; Table altered. Elapsed: 00:00:57.24
این راهکار تغییری در زمان ساخت Foreign Key ایجاد نکرده و به طور کلی استفاده از همروندی در این زمینه موثر واقع نشده است. این مسئله را می توان در فایل trace هم مشاهده کرد:
select /*+ all_rows ordered dynamic_sampling(2) */ A.rowid, :1, :2, :3 from "USEF"."TB_CHILD" A , "USEF"."ALL_TABLE" B where( "A"."ID_FK" is not null) and( "B"."ID" (+)= "A"."ID_FK") and( "B"."ID" is null)
بنابرین باید به دنبال راهکار دیگری باشیم.
اگر Foreign Key را با استفاده از عبارت enable novalidate بسازیم، Foreign Key در کسری از ثانیه ایجاد خواهد شد چرا که enable novalidate، درستی اطلاعاتی که از قبل وارد شدن را بررسی نمی کند(چک نمی کند id_fk زیر مجموعه id هست یا نه!) ولی اطلاعات جدیدی که وارد می شوند، از این جهت کنترل خواهند شد.
مزیت این روش در آن است که می توانیم validate نهایی را به صورت parallel انجام دهیم تا از درستی وابستگی اطلاعات قدیمی مطمئن شده و وضعیت Foreign Key را در حالت enable validate قرار دهیم.
SQL> ALTER TABLE tb_child ADD CONSTRAINT fk_1 FOREIGN KEY (id_fk) REFERENCES all_table(id) enable novalidate; Table altered. Elapsed: 00:00:00.05 SQL> ALTER TABLE TB_CHILD PARALLEL 10; Table altered. SQL> ALTER TABLE tb_child MODIFY CONSTRAINT fk_1 enable validate; Table altered. Elapsed: 00:00:16.67
زمان 1 دقیقه به 16 ثانیه کاهش پیدا کرده است.