تنظیم درست مقدار خصیصه cache برای sequenceها می تواند به لحاظ پرفرومنسی بسیار اثرگذار باشد البته در بعضی از موارد، به دلیل محدودیت application مجاز نیستیم برای cache مقداری بزرگتر از صفر در نظر بگیریم صرف نظر از این استثنا، گاها مشاهده می شود که بعضی از افراد بعد از ایجاد sequenceء، cache را با همان مقدار پیش فرض(عدد 20) رها می کنند در صورتی که این مقدار نمی تواند برای همه sequenceها مناسب باشد و برای آنکه sequenceها بتوانند بهتر پاسخگوی بارکاری باشند باید سایز cache را متناسب با نرخ استفاده sequence مقداردهی کرد.
اوراکل قابلیت جدیدی را ارائه کرده است که می تواند در این زمینه بسیار موثر باشد. ویژگی Sequence Dynamic Cache Resizing در اوراکل 21c ارائه شده(و بعدا در 19.10 هم اضافه شده است) و می تواند به صورت خودکار این مسئله(اندازه cache) را مدیریت کند.
براساس این ویژگی، cache size می تواند بر مبنای نرخ استفاده sequenceها کاهش و یا افزایش یابد(به صورت خودکار). البته این مقدار هیچ وقت از عددی که به صورت دستی برای خصیصه cache تنظیم شده، کمتر نمی شود. قابلیت Dynamic Cache Resizing به صورت پیش فرض فعال است.
در ادامه با ارائه یک سناریو، بیشتر با رفتار Sequence Dynamic Cache Resizing آشنا خواهیم شد.
در ابتدا sequenceای را با cache size=3 ایجاد می کنیم:
SQL> create sequence seq1 cache 3;
Sequence created
با اولین فراخوانی، sequence مقدار 1 را برمیگردد مقدار برگشتی را در جدولی ذخیره می کنیم:
SQL> create table tbtest as select seq1.nextval from dual;
Table created
SQL> select * from tbtest;
NEXTVAL
——-
1
با توجه به عدد در نظر گرفته شده برای خصیصه cache(عدد 3)، اعداد 1 تا 3 در حافظه قرار گرفته اند و اولین مقدار sequence حاضر در دیسک عدد 4 می باشد که last_number نامیده می شود:
SQL> select s.sequence_name,s.cache_size,s.last_number from user_sequences s;
SEQUENCE_N CACHE_SIZE LAST_NUMBER
———- ———- ———–
SEQ1 3 4
توجه: last_number معادل ستون highwater در جدول $seq است.
با flush کردن shared_pool و یا کرش کردن instance، مقدار بعدی که توسط sequence برمی گردد برابر خواهد بود با مقدار last_number! و اعداد موجود در حافظه از بین خواهد رفت:
SQL> alter system flush shared_pool;
System altered
SQL> insert into tbtest select seq1.nextval from dual;
1 row inserted
SQL> select * from tbtest;
NEXTVAL
——-
1
4
همانطور که می بینید، با خالی کردن shared pool، اعداد 2 و 3 از بین رفته اند.
تا اینجا نرخ استفاده از sequence چندان بالا نبود به همین دلیل، اوراکل از قابلیت Sequence Dynamic Cache Resizing هم استفاده ای نکرده است بنابرین برای انکه رفتار این ویژگی را ببینیم، باید تعداد رجوع به sequence را افزایش دهیم. به این جهت، یک میلیون بار sequence را فراخوانی کرده و خروجی را در جدول tbtest درج می کنیم:
begin
for i in 1..1000000 loop
insert into tbtest select seq1.nextval from dual;
end loop;
end;
/
با درج یک میلیون رکورد، مقدار جاری sequence و حداکثر عددی که در جدول tbtest درج شده 1000004 خواهد بود:
SQL> select seq1.currval from dual;
CURRVAL
———-
1000004
SQL> select max(nextval) from tbtest;
MAX(NEXTVAL)
————
1000004
با خالی کردن shared pool، مجددا sequence را فراخوانی می کنیم:
SQL> alter system flush shared_pool;
System altered
SQL> insert into tbtest select seq1.nextval from dual;
1 row inserted
طبق قائده متدوال در نسخ قبل از 21c، انتظار داریم nextval به دو عدد بالاتر افزایش پیدا کند یعنی 1000004 به 1000006 تغییر کند اما نتیجه چیز دیگری خواهد بود:
SQL> select max(nextval) from tbtest;
MAX(NEXTVAL)
————
1009772
SQL> select seq1.currval from dual;
CURRVAL
———-
1009772
این تفاوت به فعال بودن ویژگی Sequence Dynamic Cache Resizing برمی گردد. با توجه به آنکه مقدار nextval را در جدول tbtest ذخیره کرده ایم، گپ ایجاد شده با دستور زیر هم قابل مشاهده خواهد بود:
SQL> select * from tbtest order by 1 desc fetch first 4 rows only;
NEXTVAL
——-
1009772
1000004
1000003
1000002
در صورت حساسیت application با گپ احتمالی، می توان این ویژگی را غیرفعال کرد:
SQL> alter system set “_dynamic_sequence_cache” = FALSE;
System altered