سلام
اعتقاد دارم بسیاری از بهینه سازی های دستورات با تفکر صحیح نسبت به مسئله به دست می آید و خیلی از اوقات نوع نگرش و نحوه حل مسئله در نحوه عملکرد و نتیجه بسیار تاثیر گذار است. به عنوان مثال یکی از بهینه سازی های بسیار ساده که در جاهای مختلف نمونه هایی از آن را دیده ام و با یک تغییر بسیار ساده نتایج عالی گرفتیم را با شما در میان می گذارم.
فرض کنید جدولی داریم با صد هزار رکورد که تنها 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' از ایندکس استفاده نمی شود و هزینه اجرای آنها بسیار متفاوت است.
بسیاری از بهینه سازی ها با بهینه سازی نحوه تفکر ما حاصل می شوند.
موفق باشید
- ۹۹/۰۶/۰۵