ویژگی Memoptimized Rowstore – Fast Ingest در اوراکل 19c

همانطور که می دانید، IOT Deviceها به طور پیوسته جریانی از داده را به سمت دیتابیس هدایت می کنند به طوری که درج این داده ها در دیتابیس رابطه ای می تواند با چالشهای پرفورمنسی همراه باشد.

در اوراکل نسخه 19c ، راهکاری برای حل این مسئله پرفورمنسی ارائه شد که مطابق با آن، این دسته از دیتا ابتدأَ در حافظه ثبت شده و در نهایت به صورت دسته ای به دیسک منتقل می شوند. این قابلیت جدید، Memoptimized Rowstore Fast Ingest نام دارد.

البته به این ویژگی اصطلاحا deferred insert هم گفته می شود چرا که ابتدا دیتا در قسمتی از large pool ثبت می شود و بعد از گذشت مدت زمانی، به صورت خودکار توسط اوراکل به دیسک منتقل شده و در زمانی که دیتا در Large Pool قرار دارد، توسط sessionهای دیگر قابل رویت نخواهد بود.

توجه: استفاده از ویژگی Fast Ingest برای امور متداول در دیتابیسهای OLTP، به هیچ وجه توصیه نمی شود چرا که در شرایطی چون کرش کردن instance و یا پر شدن فضا tablespaceها ممکن است Data loss رخ دهد.

 

فعالسازی و استفاده از Fast Ingest

قابلیت Fast Ingest در محیط Cloud و Exadata قابل استفاده است بنابرین برای استفاده از این ویژگی در محیط on-premise، باید پارامتر exadata_feature_on را فعال کرد:

alter system set “_exadata_feature_on”=true scope=spfile;

در غیر این صورت، با خطای زیر مواجه خواهیم شد:

ORA-12754: Feature ‘Memoptimized Rowstore’ is disabled due to missing capability ‘Runtime Environment’.

برای استفاده از ویژگی Fast Ingest، باید خصیصه MEMOPTIMIZE FOR WRITE را در سطح جدول تنظیم کنیم. این کار در زمان ایجاد جدول و یا بعد از ایجاد آن(از طریق دستور alter table) قابل انجام است:

SQL> create table TBL1

  2  (

  3    id   NUMBER not null,

  4    text VARCHAR2(3000)

  5  )

  6  MEMOPTIMIZE FOR WRITE;

ORA-62145: MEMOPTIMIZE FOR WRITE feature not allowed on segment with deferred storage.

همانطور که می بینید، صرف استفاده از خصیصه MEMOPTIMIZE FOR WRITE کافی نخواهد بود و ایجاد فوری SEGMENT هم برای استفاده از این ویژگی ضروری می باشد این کار با تنظیم پارامتر deferred_segment_creation به مقدار false و یا استفاده از عبارت SEGMENT CREATION IMMEDIATE در متن دستور ایجاد جدول، انجام خواهد شد:

SQL> create table TBL1

  2  (

  3    id   NUMBER not null,

  4    text VARCHAR2(3000)

  5  )

  6  SEGMENT CREATION IMMEDIATE

  7  MEMOPTIMIZE FOR WRITE;

Table created

در صورتی که جدول قبلا ایجاد شده، می توان از طریق دستور زیر، خصیصه MEMOPTIMIZE FOR WRITE را برای جدول تنظیم کرد:

SQL> ALTER TABLE tbl1 MEMOPTIMIZE FOR WRITE;

Table altered

ویژگی Fast Ingest در سطح جدول فعال شد اما این کافی نیست و در شرایط فعلی، تمامی insertها بر روی جدول tbl1 به صورت Conventional اجرا خواهند شد!!!

برای درج اطلاعات به روش Fast Ingest، باید از hintای به نام MEMOPTIMIZE_WRITE استفاده کرد:

INSERT /*+ MEMOPTIMIZE_WRITE */ INTO tbl1 VALUES (1,’aaaaaa’);

توجه: غیرفعال کردن قابلیت Fast Ingest برای یک جدول، با دستور زیر انجام می شود:

SQL> ALTER TABLE tbl1 no MEMOPTIMIZE FOR WRITE;

Table altered

 

مقایسه پرفورمنسی بین Fast Ingest insert و Conventional insert

در قطعه کد زیر سعی داریم ده میلیون رکورد را به صورت متداول در جدول tbl1 درج کنیم، این کار چند ثانیه طول می کشد؟

SQL> begin

  2  for i in 1..10111000

  3  loop

  4    insert /*+Conventional insert*/ into usef.tbl1 values (i, ‘abcdefg’);

  5  end loop;

  6  commit;

  8  end;

  9  /

PL/SQL procedure successfully completed.

Elapsed: 00:07:08.26

SQL> select count(*) from tbl1;

  COUNT(*)

———-

  10111000

درج رکوردها در مدت زمان 7 دقیقه انجام شده است و البته بعد از این مدت زمان نسبتا طولانی، رکوردها توسط تمامی sessionها قابلی رویت هستند و با crash کردن instance دیتایی از بین نخواهد رفت.

همین کار را این بار با استفاده از ویژگی Fast Ingest تکرار می کنیم:

SQL>  truncate table usef.tbl1;

Table truncated

SQL> ALTER TABLE tbl1 MEMOPTIMIZE FOR WRITE;

Table altered

SQL> begin

  2  for i in 1..10111000

  3  loop

  4    insert /*+ MEMOPTIMIZE_WRITE */ into usef.tbl1 values (i, ‘abcdefg’);

  5  end loop;

  6  commit;

  8  end;

  9  /

PL/SQL procedure successfully completed.

Elapsed: 00:01:09.80

SQL> select count(*) from usef.tbl1;

  COUNT(*)

———-

  10038692

 

  همانطور که می بینید، با روش Fast Ingest، عملیات درج اطلاعات با سرعت بسیار بالای انجام شده و البته درصدی از اطلاعات هنوز در Large Pool قرار دارند که در آینده به صورت خودکار توسط اوراکل به دیسک منتقل خواهند شد البته اگر قبل از این انتقال، instance به هر دلیلی crash کند، این میزان از اطلاعات از دست خواهند رفت(حدود 72308 رکورد). برای انتقال دستی این اطلاعات به دیسک، می توان دستور زیر استفاده کرد:

SQL> begin

  2    dbms_memoptimize_admin.writes_flush();

  3    end;

  4  /

PL/SQL procedure successfully completed

Executed in 0.015 seconds

با اجرای این پروسیجر، 72308 رکورد باقیمانده در حافظه هم به دیسک منتقل خواهند شد:

SQL> select count(*) from usef.tbl1;

  COUNT(*)

———-

  10111000

بنابرین شاید بهتر باشد که این پروسیجر را به قطعه کد فوق اضافه کنیم:

SQL>truncate table usef.tbl1;

Table truncated

SQL>begin

for i in 1..10111000

loop

  insert /*+ MEMOPTIMIZE_WRITE */ into usef.tbl1 values (i, ‘abcdefg’);

end loop;

commit;

dbms_memoptimize_admin.writes_flush();

end;

/

Elapsed: 00:01:18.86

SQL> select count(*) from usef.tbl1;

  COUNT(*)

———-

  10111000

فضایی که برای memoptimize_write_area مصرف شده را با پرس و جوی زیر می بینیم:

select round(total_size/1024/1024) total_size_MB,round(used_space/1024/1024) used_space_MB,round(free_space/1024/1024)  free_space_MB from v$memoptimize_write_area;

 

نکات پایانی:

1.اگر اطلاعاتی از جدول در Large Pool موجود باشد، عملیات truncate، صرفا بر روی قسمتی از اطلاعات جدول که در دیسک موجود هستند، انجام خواهد شد:

SQL> truncate table usef.tbl1;

Table truncated.

SQL> insert /*+ MEMOPTIMIZE_WRITE */into usef.tbl1 values (1, ‘abcdefg’);

1 row created.

SQL> commit;

Commit complete.

SQL> select count(*) from usef.tbl1;

  COUNT(*)

———-

         0

SQL> truncate table usef.tbl1;

Table truncated.

SQL> exec  dbms_memoptimize_admin.writes_flush();

PL/SQL procedure successfully completed.

SQL> select count(*) from usef.tbl1;

  COUNT(*)

———-

         1

2.استفاده از روش Fast Ingest سه خطر احتمالی زیر را در پی دارد:

الف: در صورت crash کردن instance، اطلاعاتی که در Large Pool قرار دارند، از بین خواهند رفت.

 ب: اطلاعات درج شده، معمولا بلافاصله قابل رویت نیستند.

ج: با اتفاقاتی چون پر شدن فضای دیتابیس و tablespace و … ممکن است دیتا از دست برود.

ارتباط با نویسنده مطلب:vahidusefzadeh@ کانال تخصصی اوراکل و لینوکس: OracleDB@

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

نشانی ایمیل شما منتشر نخواهد شد.