之前,我发现执行计划中的“成本”可以很好地指示相对执行时间。为什么这个案例有所不同?我认为执行计划具有相关性是傻瓜吗?我具体可以尝试什么来提高 v_test 性能?
谢谢。
使用 Oracle 10g,我在下面定义了一个简单的查询 View
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))
定义替换以下 View
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, 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 = '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, 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 = 'PROD' and
trim(R.PROD_ID) = UPPER(trim(D.PROD_ID))
union all
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 = 'DIV' and
trim(R.DIV_ID) = UPPER(trim(D.DIV_ID))
union all
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 = '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, 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 = 'CLUS' and
trim(R.CLUS_ID) = UPPER(trim(D.CLUS_ID))
union all
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 = '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, 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 = '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 的执行计划明显低于 simple 的 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_ENTRY.RPE_KEY,
CT_REPORT_ENTRY.CUSTOM16,
Exp_Sub_Type.value,
CT_REPORT.PAID_DATE
执行时间截然不同。 v_test View 需要 15 小时,v_bo_secured_detail 需要几秒钟。
<小时/>感谢所有回复的人
这对我来说是值得记住的。表达式的理论和数学与基于硬件的执行的现实相结合的地方。哎哟。
最佳答案
执行计划是理论,执行时间是现实。
该计划向您展示了引擎如何执行查询,但某些步骤可能会导致解决查询所需的工作量过多。使用“x is null or x = y”的味道很糟糕。如果 r 和 d 是大表,您可能会遇到某种组合爆炸,并且请求会在大型磁盘 block 列表中无休止地循环。我想您在执行过程中会看到大量 I/O。
另一方面,联合选择又短又甜,因此可能会重用早期选择中仍然存在的大量磁盘 block ,并且/或者您可以从同一磁盘上的读取中获得一定程度的并行性 block 。到处使用trim()和upper()看起来有点可疑。如果您的数据如此不干净,可能值得时常进行一些定期清理,以便您可以说“x = y”并知道它有效。
更新:您询问了改进 v_test 的技巧。清理你的数据,这样就不需要trim()和upper()了。它们可能会阻止使用索引(尽管这也会影响联合选择版本)。
如果你无法摆脱“x is null or x = y”,那么 y = nvl(x,'does-not-exist') 可能有更好的特征(假设 'does-not-exist' 是一个“不可能发生”id 值)。
关于oracle - 解释计划成本与执行时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/102477/