在此之前,我发现执行计划中的“成本”是相对执行时间的良好指标.为什么这种情况不同?我认为执行计划具有相关性我是个傻瓜吗?具体可以尝试提高v_test的性能?
谢谢.
使用Oracle 10g我有一个简单的查询视图定义如下
create or replace view v_test as select distinct u.bo_id as bo_id,upper(trim(d.dept_id)) as dept_id from cust_bo_users u join cust_bo_roles r on u.role_name=r.role_name join cust_dept_roll_up_tbl d on (r.region is null or trim(r.region)=trim(d.chrgback_reg)) and (r.prod_id is null or trim(r.prod_id)=trim(d.prod_id)) and (r.div_id is null or trim(r.div_id)=trim(d.div_id )) and (r.clus_id is null or trim(r.clus_id )=trim( d.clus_id)) and (r.prod_ln_id is null or trim(r.prod_ln_id)=trim(d.prod_ln_id)) and (r.dept_id is null or trim(r.dept_id)=trim(d.dept_id))
定义为替换以下视图
create or replace view v_bo_secured_detail select distinct Q.BO_ID,Q.DEPT_ID from (select U.BO_ID BO_ID,UPPER(trim(D.DEPT_ID)) DEPT_ID from CUST_BO_USERS U,CUST_BO_ROLES R,CUST_DEPT_ROLL_UP_TBL D where U.ROLE_NAME = R.ROLE_NAME and R.ROLE_LEVEL = 'REGION' and trim(R.REGION) = UPPER(trim(D.CHRGBACK_REG)) union all select U.BO_ID BO_ID,CUST_DEPT_ROLL_UP_TBL D where U.ROLE_NAME = R.ROLE_NAME and R.ROLE_LEVEL = 'RG_PROD' and trim(R.REGION) = UPPER(trim(D.CHRGBACK_REG)) and trim(R.PROD_ID) = UPPER(trim(D.PROD_ID)) union all select U.BO_ID BO_ID,CUST_DEPT_ROLL_UP_TBL D where U.ROLE_NAME = R.ROLE_NAME and R.ROLE_LEVEL = 'PROD' and trim(R.PROD_ID) = UPPER(trim(D.PROD_ID)) union all select U.BO_ID BO_ID,CUST_DEPT_ROLL_UP_TBL D where U.ROLE_NAME = R.ROLE_NAME and R.ROLE_LEVEL = 'DIV' and trim(R.DIV_ID) = UPPER(trim(D.DIV_ID)) union all select U.BO_ID BO_ID,CUST_DEPT_ROLL_UP_TBL D where U.ROLE_NAME = R.ROLE_NAME and R.ROLE_LEVEL = 'RG_DIV' and trim(R.REGION) = UPPER(trim(D.CHRGBACK_REG)) and trim(R.DIV_ID) = UPPER(trim(D.DIV_ID)) union all select U.BO_ID BO_ID,CUST_DEPT_ROLL_UP_TBL D where U.ROLE_NAME = R.ROLE_NAME and R.ROLE_LEVEL = 'CLUS' and trim(R.CLUS_ID) = UPPER(trim(D.CLUS_ID)) union all select U.BO_ID BO_ID,CUST_DEPT_ROLL_UP_TBL D where U.ROLE_NAME = R.ROLE_NAME and R.ROLE_LEVEL = 'RG_CLUS' and trim(R.REGION) = UPPER(trim(D.CHRGBACK_REG)) and trim(R.CLUS_ID) = UPPER(trim(D.CLUS_ID)) union all select U.BO_ID BO_ID,CUST_DEPT_ROLL_UP_TBL D where U.ROLE_NAME = R.ROLE_NAME and R.ROLE_LEVEL = 'PROD_LN' and trim(R.PROD_LN_ID) = UPPER(trim(D.PROD_LN_ID)) union all select U.BO_ID BO_ID,UPPER(trim(R.DEPT_ID)) DEPT_ID from CUST_BO_USERS U,CUST_BO_ROLES R where U.ROLE_NAME = R.ROLE_NAME and R.ROLE_LEVEL = 'DEPT') Q
目标是删除对ROLE_LEVEL列的依赖.
为简单起见,v_test的执行计划明显低于v_bo_secured_detail
select * from <view> where bo_id='value'
查询.并且在真实世界查询中使用时显着降低
select CT_REPORT.RPT_KEY,CT_REPORT_ENTRY.RPE_KEY,CT_REPORT_ENTRY.CUSTOM16,Exp_Sub_Type.value,min(CT_REPORT_PAYMENT_CONF.PAY_DATE),CT_REPORT.PAID_DATE from CT_REPORT,<VIEW> SD,CT_REPORT_ENTRY,CT_LIST_ITEM_LANG Exp_Sub_Type,CT_REPORT_PAYMENT_CONF,CT_STATUS_LANG Payment_Status where (CT_REPORT_ENTRY.RPT_KEY = CT_REPORT.RPT_KEY) and (Payment_Status.STAT_KEY = CT_REPORT.PAY_KEY) and (Exp_Sub_Type.LI_KEY = CT_REPORT_ENTRY.CUSTOM9 and Exp_Sub_Type.LANG_CODE = 'en') and (CT_REPORT.RPT_KEY = CT_REPORT_PAYMENT_CONF.RPT_KEY) and (SD.BO_ID = 'JZHU9') and (SD.DEPT_ID = UPPER(CT_REPORT_ENTRY.CUSTOM5)) and (Payment_Status.name = 'Payment Confirmed' and (Payment_Status.LANG_CODE = 'en') and CT_REPORT.PAID_DATE > to_date('01/01/2008','mm/dd/yyyy') and Exp_Sub_Type.value != 'Korea') group by CT_REPORT.RPT_KEY,CT_REPORT.PAID_DATE
执行时间差异很大. v_test视图需要15个小时,而v_bo_secured_detail需要几秒钟.
?
谢谢所有回复的人
这是我要记住的一个.表达式的理论和数学符合基于硬件的执行的现实的地方.哎哟.
解决方法
如
the Oracle documentation says所示,成本是相对于特定执行计划的估计成本.调整查询时,相对于计算成本的特定执行计划可能会发生变化.有时戏剧性.
v_test性能的问题在于Oracle除了执行嵌套循环之外无法执行它,对于每个cust_bo_roles,扫描所有cust_dept_roll_up_tbl以查找匹配项.如果表的大小为n和m,则需要n * m的时间,这对于大型表来说很慢.相比之下,v_bo_secured_detail被设置为一系列查询,每个查询都可以通过其他机制完成. (Oracle有一个它可以使用的数字,包括使用索引,动态构建哈希,或者对数据集进行排序和合并.这些操作都是O(n * log(n))或更好.)一小部分快速查询很快.
尽管很痛苦,如果你想让这个查询更快,那么你需要像以前的查询一样将其分解出来.