سلام
اعتقاد دارم بسیاری از بهینه سازی های دستورات با تفکر صحیح نسبت به مسئله به دست می آید و خیلی از اوقات نوع نگرش و نحوه حل مسئله در نحوه عملکرد و نتیجه بسیار تاثیر گذار است. به عنوان مثال یکی از بهینه سازی های بسیار ساده که در جاهای مختلف نمونه هایی از آن را دیده ام و با یک تغییر بسیار ساده نتایج عالی گرفتیم را با شما در میان می گذارم.
فرض کنید جدولی داریم با صد هزار رکورد که تنها 10 رکورد آن دارای flag=Y است و بقیه رکوردها دارای مقدار flag=N هستند، این جدول را می سازیم:
create table Mytest_tbl
as
select rownum as "ID",decode(mod(rownum,10000),0,'Y','N') as my_flag from dual connect by level <= 100000;
select my_flag,count(*) from Mytest_tbl
group by my_flag;
برای ستون my_flag این جدول یک ایندکس می سازیم:
create index IDX_MY_FLAG on Mytest_tbl (MY_FLAG);
آمار جدول را به روز می کنیم:
begin
dbms_stats.gather_table_stats(
ownname=> user,
tabname=> 'MYTEST_TBL'
,Estimate_Percent => SYS.DBMS_STATS.AUTO_SAMPLE_SIZE
,Method_Opt => 'FOR ALL COLUMNS SIZE AUTO'
,Degree => SYS.DBMS_STATS.DEFAULT_DEGREE
,Cascade => TRUE
,No_Invalidate => SYS.DBMS_STATS.AUTO_INVALIDATE);
end;
حالا می خواهیم مقادیری که ستون my_flag مقدار Y دارد را به دست آوریم، در نظر داشته باشید که این کار به دو روش امکان پذیر است، یکی اینکه بگوییم My_Flag = ’Y’ و دیگری My_Flag != ’N’
با اینکه هر دو شرط درست هستند و نتایج یکسانی به ما می دهند، اما در واقع عملکرد متفاوتی دارند:
روش اول (My_Flag!=’N’)
select * from Mytest_tbl t
where t.MY_Flag != 'N';
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost | Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 10 | 70 | 47 | 00:00:01 |
| * 1 | TABLE ACCESS FULL | MYTEST_TBL | 10 | 70 | 47 | 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
------------------------------------------
* 1 - filter("T"."MY_FLAG"<>'N')
روش دوم (My_Flag=’Y’):
select * from Mytest_tbl t
where t.MY_Flag = 'Y';
----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost | Time |
----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 10 | 70 | 2 | 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID BATCHED | MYTEST_TBL | 10 | 70 | 2 | 00:00:01 |
| * 2 | INDEX RANGE SCAN | IDX_MY_FLAG | 10 | | 1 | 00:00:01 |
----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
------------------------------------------
* 2 - access("T"."MY_FLAG"='Y')
همانطور که در Plan اجرای هر دو دستور مشخص است، وقتی MY_Flag = 'Y' است از ایندکس استفاده می شود ولی در حالت MY_Flag != 'N' از ایندکس استفاده نمی شود و هزینه اجرای آنها بسیار متفاوت است.
بسیاری از بهینه سازی ها با بهینه سازی نحوه تفکر ما حاصل می شوند.
موفق باشید