问题描述
CART_V_PICK_ANAL是视图顶部的视图 ..在一个有33k行的表上面。
我知道该计划是错误的,这取决于oracle如何访问此33k表。
它应该访问的方式对我来说很清楚。
我不知道我要达到什么样的限制。是 “查看深度” 是因为后退了一步吗 ..会很好的。
作为一个小的背景信息:
订单 => 700K
Orddetails =>6M
ordanalysis => 46K
Taks =>33k。
查看以下结果:
我应该如何进行?
我很确定应该有一个简单的方法。
我知道该计划是错误的,这取决于oracle如何访问此33k表。
它应该访问的方式对我来说很清楚。
我不知道我要达到什么样的限制。是 “查看深度” 是因为后退了一步吗 ..会很好的。
作为一个小的背景信息:
订单 => 700K
Orddetails =>6M
ordanalysis => 46K
Taks =>33k。
查看以下结果:
SQL> select orderid from orders where ordercode = '#00000000820 '; ORDERID ---------- 4538931 Elapsed: 00:00:00.048 SQL> sELECT * FROM CART_V_PICK_ANAL WHERE orderid = 4538931 ; WAREHOUSEID ORDERSGROUP ORDERID LOCATIONID PREPACKAGEID ITEMID STOCKSTATUSID WMSSTATUSID LU1PERLU2 SUM_CARTQTY SUMPICKQTY CURPICKQTY RUNPICKINGQTY PICKINGQTY SUM_BOXQTY DETLINES VS_LOTID VS_DATEIN LOTID TASKTYPE PICKINGTYPE ORDANALID TASKID DATEIN ----------- -------------------- ---------- ---------- ------------ ---------- ------------- ----------- ---------- ----------- ---------- ---------- ------------- ---------- ---------- ---------- ---------- --------- ---------- ---------- ----------- ---------- ---------- -------- 9 4538931 4538931 89328 157357 60 11 48 10 10 10 10 10 0 1 25 3 28344677 3044260 16/03/18 9 4538931 4538931 90813 150503 60 11 75 0 75 75 75 0 1 1 25 3 28344675 3042539 21/09/17 ... 23 rows selected. Elapsed: 00:00:00.038 SQL> sELECT * FROM CART_V_PICK_ANAL WHERE orderid in (select orderid from orders where ordercode = '#00000000820 '); WAREHOUSEID ORDERSGROUP ORDERID LOCATIONID PREPACKAGEID ITEMID STOCKSTATUSID WMSSTATUSID LU1PERLU2 SUM_CARTQTY SUMPICKQTY CURPICKQTY RUNPICKINGQTY PICKINGQTY SUM_BOXQTY DETLINES VS_LOTID VS_DATEIN LOTID TASKTYPE PICKINGTYPE ORDANALID TASKID DATEIN ----------- -------------------- ---------- ---------- ------------ ---------- ------------- ----------- ---------- ----------- ---------- ---------- ------------- ---------- ---------- ---------- ---------- --------- ---------- ---------- ----------- ---------- ---------- -------- 9 4538931 4538931 89328 157357 60 11 48 10 10 10 10 10 0 1 25 3 28344677 3044260 16/03/18 9 4538931 4538931 90813 150503 60 11 75 0 75 75 75 0 1 1 25 3 28344675 3042539 21/09/17 .. 23 rows selected. Elapsed: 00:01:48.513复制
我应该如何进行?
我很确定应该有一个简单的方法。
专家解答
简短的答案是优化器不知道子查询选择orderid的哪个值。所以它的行估计不太准确。
这个简单的演示显示了为什么这可能是一个问题。有一张表有100行。其中1的值为1,其余为99。如果搜索值1,则优化器知道此值只有一行,因此此表的E (stimable) 行是一行:
相反,如果你
-创建具有值1和99的两行表
-通过使用t2查询,从第一个表中查找值为1的行
优化器不知道它将从t2获取哪一行。因此,它对冲了赌注,并从t1开始估计50行:
所以我的猜测是使用子查询时不太准确的行估计意味着优化器更改访问路径。
有可能还有别的事情发生。在任何情况下,为了准确地找出为什么有不同的计划为您的查询,请像我所做的那样获取执行计划,并在这里分享它们:
这个简单的演示显示了为什么这可能是一个问题。有一张表有100行。其中1的值为1,其余为99。如果搜索值1,则优化器知道此值只有一行,因此此表的E (stimable) 行是一行:
create table t1 as select case level when 1 then 1 else 99 end c1 from dual connect by level <= 100; exec dbms_stats.gather_table_stats ( user, 't1', method_opt => 'for columns c1 size 2' ) ; set serveroutput off alter session set statistics_level = all; select * from t1 where c1 = 1; select * from table(dbms_xplan.display_cursor(null, null, 'ROWSTATS LAST')); /* PLAN_TABLE_OUTPUT SQL_ID 54cws9vns3mbp, child number 0 ------------------------------------- select * from t1 where c1 = 1 Plan hash value: 3617692013 ------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | ------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 1 | |* 1 | TABLE ACCESS FULL| T1 | 1 | 1 | 1 | ------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("C1"=1) */复制
相反,如果你
-创建具有值1和99的两行表
-通过使用t2查询,从第一个表中查找值为1的行
优化器不知道它将从t2获取哪一行。因此,它对冲了赌注,并从t1开始估计50行:
create table t2 ( c1 int ); insert into t2 values ( 1 ); insert into t2 values ( 99 ); exec dbms_stats.gather_table_stats ( user, 't2' ) ; select * from t1 where c1 = ( select c1 from t2 where c1 = 1 ); select * from table(dbms_xplan.display_cursor(null, null, 'ROWSTATS LAST')); /* PLAN_TABLE_OUTPUT SQL_ID 6hcsxnm979h57, child number 0 ------------------------------------- select * from t1 where c1 = ( select c1 from t2 where c1 = 1 ) Plan hash value: 1484901111 -------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | -------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 1 | |* 1 | TABLE ACCESS FULL | T1 | 1 | 50 | 1 | |* 2 | TABLE ACCESS FULL| T2 | 1 | 1 | 1 | -------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("C1"=) 2 - filter("C1"=1) */复制
所以我的猜测是使用子查询时不太准确的行估计意味着优化器更改访问路径。
有可能还有别的事情发生。在任何情况下,为了准确地找出为什么有不同的计划为您的查询,请像我所做的那样获取执行计划,并在这里分享它们:
set serveroutput off alter session set statistics_level = all; select * fromselect * from table(dbms_xplan.display_cursor(null, null, 'ALLSTATS LAST')); 复制
文章转载自ASKTOM,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。
评论
相关阅读
【纯干货】Oracle 19C RU 19.27 发布,如何快速升级和安装?
Lucifer三思而后行
655次阅读
2025-04-18 14:18:38
Oracle RAC 一键安装翻车?手把手教你如何排错!
Lucifer三思而后行
625次阅读
2025-04-15 17:24:06
Oracle数据库一键巡检并生成HTML结果,免费脚本速来下载!
陈举超
530次阅读
2025-04-20 10:07:02
【ORACLE】记录一些ORACLE的merge into语句的BUG
DarkAthena
479次阅读
2025-04-22 00:20:37
【活动】分享你的压箱底干货文档,三篇解锁进阶奖励!
墨天轮编辑部
475次阅读
2025-04-17 17:02:24
一页概览:Oracle GoldenGate
甲骨文云技术
457次阅读
2025-04-30 12:17:56
【ORACLE】你以为的真的是你以为的么?--ORA-38104: Columns referenced in the ON Clause cannot be updated
DarkAthena
449次阅读
2025-04-22 00:13:51
火焰图--分析复杂SQL执行计划的利器
听见风的声音
405次阅读
2025-04-17 09:30:30
3月“墨力原创作者计划”获奖名单公布
墨天轮编辑部
369次阅读
2025-04-15 14:48:05
Oracle数据库Hint大全,31个使用案例,速来下载!
陈举超
343次阅读
2025-04-16 21:25:19