oracle - 解释计划成本与执行时间

标签 oracle optimization

之前,我发现执行计划中的“成本”可以很好地指示相对执行时间。为什么这个案例有所不同?我认为执行计划具有相关性是傻瓜吗?我具体可以尝试什么来提高 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/

相关文章:

java - Java中如何保证Closeable接口(interface)的close()方法的幂等性?

sql - 在 Oracle 的 Greatest 函数中处理 Null

python - 有没有更快的方法来添加两个二维 numpy 数组

c - 我应该使用什么类型才能获得最快的计算速度?

mysql - 优化MySQL查询,选择内选择,多个相同

oracle - Pgx 内存不足错误 : maximum off-heap size is configured to not exceed 8, 192 MB

sql - 使用 Xquery 和多个嵌套命名空间查询 Oracle 数据库 XML 数据类型列

c++ - 最好的C++编译器?

matlab - 如何在 Matlab 中优化嵌入循环索引以实现并行化?

sql - Oracle 将多列合并为一列