暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 我有一个疑问,在我的拙见中,优化器可能会失败,并且无法弄清楚原因!

ASKTOM 2020-08-14
186

问题描述

CART_V_PICK_ANAL是视图顶部的视图 ..在一个有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) 行是一行:

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 * from 

select * 
from   table(dbms_xplan.display_cursor(null, null, 'ALLSTATS LAST'));
复制

文章转载自ASKTOM,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论