قابلیت Shrink کردن Bigfile tablespace در اوراکل 23c

از نسخه های قدیمی اوراکل امکان resize کردن دیتافایلها وجود دارد:

SQL*Plus: Release 10.1.0.4.2 - Production on Tue Nov 21 11:15:16 2023
SQL> select bytes/1024/1024 SIZE_MB from v$datafile where file#=29;
   SIZE_MB
----------
      1024
SQL> alter database datafile 29 resize 120m;
Database altered.
SQL> select bytes/1024/1024 SIZE_MB from v$datafile where file#=29;
   SIZE_MB
----------
       120

البته resize کردن دیتافایلها همیشه با موفقیت انجام نمی شود و بعضا با آزاد بودن درصد بالایی از فضای دیتافایل، به دلیل قرار گرفتن بعضی از بلاکهای segment بر سر High Water Mark، امکان کاهش سایز دیتافایل وجود ندارد و در این حالت به خطای زیر برخواهیم خورد:

SQL> alter database datafile 1 resize 10m;
ORA-03297: file contains used data beyond requested RESIZE value

برای جلوگیری از خطای ORA-03297، باید segmentای که بر سر راه High Water Mark قرار دارد را جابجا کنیم! که البته قبلا در مطلبی به طور مفصل این مسئله را بررسی کردیم و از تکرار آن خودداری می کنیم.

مسئله ای که در این متن به آن خواهیم پرداخت، موضوع shrink کردن در سطح tablespaceها است. در نسخه 11g امکان shrink کردن Temporary tablespaceها به وجود آمد:

SQL*Plus: Release 11.2.0.4.0 Production on Tue Nov 21 10:35:57 2023
SQL> select FILE#,BYTES/1024/1024 from v$tempfile where file#=5;
     FILE# BYTES/1024/1024
---------- ---------------
         5            5120
SQL> ALTER TABLESPACE Temp_TBS SHRINK SPACE KEEP 340m;
Tablespace altered.
SQL> select FILE#,BYTES/1024/1024 from v$tempfile where file#=5;
     FILE# BYTES/1024/1024
---------- ---------------
         5             340

و نهایتا در نسخه 23c اوراکل این امکان را برای Bigfile Tablespaceها ارائه کرده است این کار با استفاده از پروسیجر dbms_space.tablespace_shrink امکان پذیر است که در ادامه نحوه استفاده از آن را شرح خواهیم داد.

ابتدا محیط تست را با ایجاد یک tablespace و چند segment آماده می کنیم:

Oracle Database 23c Free, Release 23.0.0.0.0 - Developer-Release
SQL> create bigfile tablespace Barname_TBS datafile size 5g;
Tablespace created.
SQL> create table usef.Jadval1 tablespace Barname_TBS as select * from tbl1;
Table created.
SQL> create index usef.innn1 on usef. Jadval1(name) tablespace Barname_TBS;
Index created.
SQL> create index usef.innn2 on usef. Jadval1(LINE) tablespace Barname_TBS;
Index created.
SQL> create table usef.T1 tablespace Barname_TBS as select * from v$datafile;
Table created.
SQL> create table usef.T2 tablespace Barname_TBS as select * from v$datafile;
Table created.

اندازه هر کدام از این segmentها را می توان با دستور زیر مشاهده کرد:

SQL> select bytes/1024/1024 SEG_SIZE_MB,segment_name from dba_segments where tablespace_name='BARNAME_TBS' order by 1;
SEG_SIZE_MB SEGMENT_NA
----------- ----------
      .0625 T2
      .0625 T1
        172 INNN2
        280 INNN1
       1600 JADVAL1

با ایجاد segmentهای فوق، فضای اشغال شده در Barname_TBS به دو گیگابایت خواهد رسید:

SQL> select sum(bytes) TBS_SIZE from dba_segments where tablespace_name='BARNAME_TBS';
  TBS_SIZE
----------
2151809024

پارامترهای مربوط به پروسیجر dbms_space.tablespace_shrink را بازبینی می کنیم:

PROCEDURE TABLESPACE_SHRINK
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 TS_NAME                        VARCHAR2                IN
 SHRINK_MODE                    NUMBER                  IN     DEFAULT
 TARGET_SIZE                    NUMBER                  IN     DEFAULT
 SHRINK_RESULT                  CLOB                    OUT

قبل از shrink کردن tablespace می توانیم با کمک این پروسیجر، tablespace را آنالیز کنیم این کار با تنظیم پارامتر shrink_mode به DBMS_SPACE.TS_MODE_ANALYZE قابل انجام است:

SQL> set serveroutput on;
SQL> execute dbms_space.tablespace_shrink(TS_NAME=>'BARNAME_TBS', shrink_mode =>DBMS_SPACE.TS_MODE_ANALYZE);
-------------------ANALYZE RESULT-------------------
Total Movable Objects: 0
Total Movable Size(GB): 0
Orginal Datafile Size(GB): 5
Suggested Target Size(GB): 3.91
Process Time: +00 00:00:01.461820
PL/SQL procedure successfully completed.

همانطور که می بینید در صورت اجرای tablespace_shrink، حجم tablespace می تواند به 3.91GB برسد بدون آنکه objectای بخواهد جابجا شود. ایندکسی را حذف کرده و دستور فوق را دوباره اجرا می کنیم:

SQL> drop index INNN;
Index dropped. 
SQL> execute dbms_space.tablespace_shrink(TS_NAME=>'BARNAME_TBS', shrink_mode =>DBMS_SPACE.TS_MODE_ANALYZE);
-------------------ANALYZE RESULT-------------------
Total Movable Objects: 0
Total Movable Size(GB): 0
Orginal Datafile Size(GB): 5
Suggested Target Size(GB): 3.64
Process Time: +00 00:00:01.184724

در صورت اجرای tablespace_shrink، حجم tablespace می تواند به 3.64GB برسد و میزانی از فضای tablespace آزاد خواهد شد بنابرین عملیات shrink را اجرا خواهیم کرد. البته قبل از انجام، بهتر است سایز تنها datafile متعلق به این tablespace را هم ببنیم:

SQL> select bytes from v$datafile where file#=23;
     BYTES
----------
5368709120

بعد از مشاهده سایز دیتافایل، tablespace را shrink می کنیم:

SQL> execute dbms_space.tablespace_shrink(TS_NAME=>'BARNAME_TBS');
-------------------SHRINK RESULT-------------------
Total Moved Objects: 0
Total Moved Size(GB): 0
Orginal Datafile Size(GB): 5
New Datafile Size(GB): 2.07
Process Time: +00 00:00:02.230125
PL/SQL procedure successfully completed.

عملیات shrink در مدت زمان 2 ثانیه انجام شده است و سایز datafile از 5 گیگابایت به  2.07 گیگابایت رسیده است:

SQL> select bytes from v$datafile where file#=23;
     BYTES
----------
2223177728

حذف جدول می تواند در shrink کردن tablespace موثر واقع شود ولی حذف رکوردهای جدول از طریق دستور delete اثری بر روی shrink tablespace نخواهد داشت حتی اگر تمامی رکوردهای جدول را حذف کنیم چرا که بلاکی از segmentهای آن جدول کم نخواهد شد:

SQL> select bytes from user_segments where segment_name='JADVAL1';
     BYTES
----------
1677721600 
SQL> delete JADVAL1;
10216352 rows deleted.
SQL> commit;
Commit complete.
SQL> select bytes from user_segments where segment_name='JADVAL1';
     BYTES
----------
1677721600
SQL> execute dbms_space.tablespace_shrink(TS_NAME=>'BARNAME_TBS');
-------------------SHRINK RESULT-------------------
Total Moved Objects: 0
Total Moved Size(GB): 0
Orginal Datafile Size(GB): 2.07
New Datafile Size(GB): 2.07
Process Time: +00 00:00:02.680783
PL/SQL procedure successfully completed.

اما با truncate یا حذف جدول امکان shrink کردن tablespace به وجود خواهد آمد و فضای متعلق به جدول را می توان آزاد کرد:

SQL> drop table JADVAL1;
Table dropped.
SQL> execute dbms_space.tablespace_shrink(TS_NAME=>'BARNAME_TBS');
-------------------SHRINK RESULT-------------------
Total Moved Objects: 2
Total Moved Size(GB): 0
Orginal Datafile Size(GB): 2.07
New Datafile Size(GB): .07
Process Time: +00 00:00:14.774229
PL/SQL procedure successfully completed.

پس از حذف جدول JADVAL1، پروسیجر tablespace_shrink توانست فضای متعلق به این جدول را از tablespace بگیرد البته با توجه به آنکه دو جدول T1 و T2 بر سر راه HWM قرار داشتند، ابتدا این دو جدول را به ابتدای فایل جابجا کرد و سپس این فضا را آزاد کرد:

SQL> select bytes from v$datafile where file#=23;
     BYTES
----------
  71499776

ارائه خدمات مشاوره ، پشتیبانی و نصب و راه اندازی پایگاه داده اوراکل در سراسر کشور...................... تلفن: 09128110897 ایمیل:vahidusefzadeh@gmail.com

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *