اوراکل از نسخه 12cR2 قابلیت expression tracking را ارائه کرد که بر اساس آن، توابع(اعم از سیستمی و pl/sqlای)، عملگرهای محاسباتی و بصورت کلی عبارتهای استفاده شده در متن پرس و جو ها در دیتابیس ذخیره می شوند مسئولیت این کار بر عهده optimizer است و optimizer در زمان انجام عملیات hard pars، این عبارات را در مخزنی بنام (Expression Statistics Store(ESS قرار می دهد که از طریق ویوی دیتا دیکشنری DBA_EXPRESSION_STATISTICS می توان لیستی از این عبارتها را مشاهده کرد.
برای مثال، در صورت اجرای دستور select sal/2+5 from mytbl، عبارت sal/2+5 در دیتادیکشنری ثبت خواهد شد:
SQL> select sal/2+5 from mytbl;
SAL/2+5
———-
1116
SQL> select f.SNAPSHOT,f.evaluation_count,f.EXPRESSION_TEXT from DBA_EXPRESSION_STATISTICS f where table_name=’MYTBL’;
SNAPSHOT EVALUATION_COUNT EXPRESSION_TEXT
———- —————- —————–
LATEST 1 “SAL”
LATEST 1 “SAL”/2+5
SQL> select sal/2+5 from mytbl;
SAL/2
———-
1111
SQL> select f.SNAPSHOT,f.evaluation_count,f.EXPRESSION_TEXT from DBA_EXPRESSION_STATISTICS f where table_name=’MYTBL’;
SNAPSHOT EVALUATION_COUNT EXPRESSION_TEXT
———- —————- —————–
LATEST 2 “SAL”
LATEST 2 “SAL”/2+5
توجه:ستون EVALUATION_COUNT در خروجی فوق، تعداد دفعات استفاده از عبارت sal/2+5 را نمایش می دهد.
–قابلیت expression tracking محدودیتهایی را هم به همراه دارد:
1.عبارتهای استفاده شده در دستورات inline select در نظر گرفته نمی شوند.
select sysdate,(select lower(name) from t1 where rownum=1) from dual;
2.برای هر جدول حداکثر 50 عبارت پر استفاده در ESS ذخیره خواهد شد.
3.در صورتی که همه ستونهای استفاده شده در یک عبارت(Expression) از یک جدول نباشند(همانند t1.c1*t2.c2*t3.c3) اوراکل این عبارت را ذخیره نخواهد کرد.
بسیار بدیهی است که تکرار زیاد استفاده از عبارتهای پیچیده در پرس و جو ها می تواند مصرف بالای منابع را در پی داشته باشد از این رو، اوراکل در نسخه 12cR2، قابلیتی به نام In-Memory Expression را ارائه کرد که در صورت تنظیم in-memory، می توان عبارتهای پراستفاده و یا همان hot expressionها را از طریق قابلیت expression tracking شناسایی کرد و متناظر با این عبارتها، ستونی را به جدول اضافه نمود تا بر اساس آن، نتیجه محاسبات برای هر ستون و ما به ازای هر رکورد در حافظه(in memory) ثبت شوند.
این ستونها می توانند به دو روش دستی(user-defined virtual columns) و خودکار(system-generated virtual columns) به جدول اضافه شوند که در ادامه هر دو این روشها را مرور می کنیم.
روش دستی(user-created virtual columns)
در این روش قرار است با در نظر گرفتن عبارتهای پرتکرار استفاده شده در پرس و جوها، به صورت دستی normal virtual columnای را به جداول اضافه کرد(normal = non-hidden).
برای بهره مندی از این قابلیت، باید مقدار پارامتر inmemory_virtual_columns را به یکی از دو مقادیر enable و یا manual تنظیم کرد:
manual: صرفا virtual columnای به in memory منتقل خواهد شد که خصیصه in memory برای آن تنظیم شده باشد.
enable: به صورت پیش فرض، همه ستونهای مجازی در inmemory قرار خواهند گرفت مگر آنکه به صراحت خصیصه non inmemory را برای ستونی تنظیم کرده باشیم.
Disable: هیچ یک از ستونهای مجازی در inmemory قرار نمی گیرند.
در قسمت زیر خواهیم دید که با افزودن virtual column به جدول MTBL، حجم ان در in memory افزایش خواهد یافت.
SQL> select round(INMEMORY_SIZE/1024/1024) INMEMORY_SIZE,round(BYTES/1024/1024) table_size_MB,BYTES_NOT_POPULATED,POPULATE_STATUS from v$im_segments where segment_name=’MTBL’;
INMEMORY_SIZE TABLE_SIZE_MB BYTES_NOT_POPULATED POPULATE_STATUS
————- ————- ——————- —————
1111 1536 0 COMPLETED
SQL> ALTER TABLE MTBL ADD new_id AS (id1+id2+50);
Table altered
SQL> ALTER TABLE MTBL ADD new_id2 AS (id3+id2+90);
Table altered
SQL> alter system set inmemory_virtual_columns=enable;
System altered
SQL> alter table mtbl no inmemory;
Table altered
SQL> alter table MTBL inmemory no memcompress;
Table altered
SQL> select /*+FULL(b) */ count(*) from mtbl b;
COUNT(*)
———-
83886080
SQL> select round(INMEMORY_SIZE/1024/1024) INMEMORY_SIZE,round(BYTES/1024/1024) table_size_MB,BYTES_NOT_POPULATED,POPULATE_STATUS from v$im_segments where segment_name=’MTBL’;
INMEMORY_SIZE TABLE_SIZE_MB BYTES_NOT_POPULATED POPULATE_STATUS
————- ————- ——————- —————
1616 1536 0 COMPLETED
همانطور که می بینید، اطلاعاتی که از جدول در in memory ذخیره شده، از 1111 مگابایت به 1616 مگابایت رسیده است که از حجم واقعی جدول(1536) هم بیشتر است.
روش خودکار(system-generated virtual columns)
برخلاف روشی دستی(user-defined)، که افزودن ستون به صورت دستی انجام می شد، در روش اتوماتیک(اضافه شدن خودکار ستونها به جداول)، اوراکل وظیفه دارد با رجوع به Expression Statistics Store(ESS)، عبارتهای پراستفاده و یا همان hot expressionها را برای جداول شناسایی کرده(20 عبارت پر استفاده برای هر جدول در یک بازه زمانی مشخص) و متناظر با آن، ستونی(hidden virtual column) را به جدول اضافه کند و نهایتا نتیجه محاسبات را برای هر ستون و ما به ازای هر رکورد در in memory قرار دهد.
توجه: شرط مهم استفاده از قابلیت IM expression برای یک جدول مشخص، تنظیم بودن خصیصه in memory برای آن جدول(حداقل برای چند ستون از آن جدول) می باشد.
وجود این ستونها در in memory مشابه با دیگر ستونهای جدول می باشند و تمامی مزیتهای مطرح شده برای ستونهای معمولی موجود در in memory را به همراه دارند.
مدیریت IM expressionها
برای مدیریت IM expressionها می توان از بسته DBMS_INMEMORY_ADMIN استفاده کرد یکی از پروسیجرهای این بسته، IME_CAPTURE_EXPRESSIONS می باشد که با اجرای ان، ضمن شناسایی hot expressionها، ستونی به جدول اضافه خواهد شد اسامی hidden virtual columnهای ساخته شده توسط اوراکل، با پیشوند SYS_IME شروع شده و تعداد آنها برای یک جدول حداکثر می تواند به عدد 50 برسد.
این پروسیجر خصیصه in memory را برای ستونهای جدید فعال خواهد کرد البته این خصیصه را برای ستونهای مجازی ای که دیگر در hot expressionها دیده نمی شوند، برمی دارد.
مثال زیر را ببینید:
SQL> alter table mytbl inmemory;
Table altered
SQL> desc mytbl
Name Type
—- ———-
ID1 NUMBER(10)
ID2 NUMBER(10)
SQL> select avg(id1 – id2 *10) from mytbl;
AVG(ID1-ID2*10)
—————
-322.6
SQL> exec dbms_stats.flush_database_monitoring_info;
PL/SQL procedure successfully complete
SQL> EXEC DBMS_INMEMORY_ADMIN.IME_CAPTURE_EXPRESSIONS(‘CURRENT’);
PL/SQL procedure successfully completed
SQL> desc mytbl;
Name Type Default
———————– ———- ————–
ID1 NUMBER(10)
ID2 NUMBER(10)
SYS_IME0001000002447868 NUMBER “ID1”-“ID2″*10
SQL> EXEC dbms_inmemory.repopulate (‘USEF’,’MYTBL’);
PL/SQL procedure successfully completed
مقایسه پرفورمنسی!
در قسمت زیرخواهیم دید که با قرار دادن virtual column در inmemory، سرعت اجرای پرس و جو تا چندین برابر افزایش خواهد یافت:
–virtual column no inmemory(inmemory_virtual_columns=disable)
SQL> select avg(new_id+new_id2) from MTBL;
AVG(NEW_ID+NEW_ID2)
——————-
288
Elapsed: 00:00:25.03
–virtual column inmemory(inmemory_virtual_columns=enable)
SQL> select avg(new_id+new_id2) from MTBL;
AVG(NEW_ID+NEW_ID2)
——————-
288
Elapsed: 00:00:04.10
نکات پایانی
نکته اول: برای مشاهده اسامی ستونهای اضافه شده به جدول mytbl می توان از ویوی DBA_IM_EXPRESSIONS استفاده کرد:
SQL> select x.OBJECT_NUMBER,x.COLUMN_NAME,x.SQL_EXPRESSION from DBA_IM_EXPRESSIONS x where table_name=’MYTBL’;
OBJECT_NUMBER COLUMN_NAME SQL_EXPRESSION
————- ———————— ——————
140900 SYS_IME0001000002447868 “ID1”-“ID2″*10
نکته دوم: برای حذف کردن IM expressionهای یک جدول، می توان از پروسیجر IME_DROP_EXPRESSIONS استفاده کرد:
SQL> desc mytbl;
Name Type Default
———————– ———- ————–
ID1 NUMBER(10)
ID2 NUMBER(10)
SYS_IME0001000002447868 NUMBER “ID1”-“ID2″*10
SQL> EXEC DBMS_INMEMORY.IME_DROP_EXPRESSIONS(schema_name =>’USEF’ ,table_name =>’MYTBL’ ,column_name =>’SYS_IME0001000002447868′ );
PL/SQL procedure successfully completed
SQL> desc mytbl;
Name Type
—- ———-
ID1 NUMBER(10)
ID2 NUMBER(10)
نکته سوم: برای حذف همه IM expressionهای موجود در دیتابیس می توان دستور زیر را اجرا کرد:
SQL> exec DBMS_INMEMORY_ADMIN.IME_DROP_ALL_EXPRESSIONS();
PL/SQL procedure successfully completed
Comment (1)