Oracle SQL-使用dblink时未执行VIEW PUSHED PREDICATE

时间:2019-05-28 12:38:45

标签: sql oracle view sql-execution-plan database-link

我在执行以下查询(Q1)时遇到性能问题:

select
    z_out.*,
    a_out.id
from orders a_out, test z_out
where a_out.id=z_out.id and a_out.created>trunc(sysdate) and rownum<10

orders包含数百万行; orders.id是主键,而orders.craeted已编制索引。

视图是:

create or replace view test as 
select/*+qb_name(q_outer)*/
    id,
    min(value) keep (dense_rank first order by id) as value
from (
    select/*+qb_name(q_inner)*/
        id, 
        case
            when substr(id, -1)<'5' 
                --and exists(select 1 from dual@db2)
                then 'YYY'
        end as attr_1
    from orders a1
) a2, small_table b2
where b2.attr_1 in (nvl(a2.attr_1, '#'), '*')
group by id

其中small_table b2包含约200条记录(所有列均为varchar2)。

执行Q1具有出色的性能和以下执行计划:

Plan hash value: 2906430222                                                                                                  

-----------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                             | Name                | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
-----------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                      |                     |     1 |   274 |    64   (0)| 00:00:01 |       |       |
|*  1 |  COUNT STOPKEY                        |                     |       |       |            |          |       |       |
|   2 |   NESTED LOOPS                        |                     |     1 |   274 |    64   (0)| 00:00:01 |       |       |
|   3 |    PARTITION LIST ALL                 |                     |     1 |    22 |    59   (0)| 00:00:01 |     1 |     2 |
|   4 |     PARTITION RANGE ALL               |                     |     1 |    22 |    59   (0)| 00:00:01 |     1 |  LAST |
|   5 |      TABLE ACCESS BY LOCAL INDEX ROWID| ORDERS              |     1 |    22 |    59   (0)| 00:00:01 |     1 |    29 |
|*  6 |       INDEX RANGE SCAN                | IDX_ORDERS_CREATED  |     1 |       |    57   (0)| 00:00:01 |     1 |    29 |
|   7 |    VIEW PUSHED PREDICATE              | TEST                |     1 |   252 |     5   (0)| 00:00:01 |       |       |
|*  8 |     FILTER                            |                     |       |       |            |          |       |       |
|   9 |      SORT AGGREGATE                   |                     |     1 |    55 |            |          |       |       |
|  10 |       NESTED LOOPS                    |                     |   259 | 14245 |     5   (0)| 00:00:01 |       |       |
|* 11 |        INDEX UNIQUE SCAN              | PK_ID               |     1 |    14 |     2   (0)| 00:00:01 |       |       |
|* 12 |        INDEX STORAGE FAST FULL SCAN   | IDX_MN_AN_AD_ALL    |   259 | 10619 |     3   (0)| 00:00:01 |       |       |
-----------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):                                                                          
---------------------------------------------------                                                                          

   1 - filter(ROWNUM<10)                                                                                                     
   6 - access("A_OUT"."CREATED">TRUNC(SYSDATE@!))                                                                     
   8 - filter(COUNT(*)>0)                                                                                                    
  11 - access("ID"="A_OUT"."ID")                                                                                       
  12 - storage("B2"."ATTR_1"=NVL(CASE  WHEN SUBSTR("ID",(-1))<'5' THEN 'YYY' END ,'#') OR "B2"."ATTR_1"='*')              
       filter("B2"."ATTR_1"=NVL(CASE  WHEN SUBSTR("ID",(-1))<'5' THEN 'YYY' END ,'#') OR "B2"."ATTR_1"='*')               

Q1的性能问题在视图中的行--and exists(select 1 from dual@db2)取消注释时发生。 新的执行计划是:

Plan hash value: 3271081243                                                                                                                   

----------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                              | Name                | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop | Inst   |IN-OUT|
----------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                       |                     |     1 |   288 |  5273K  (1)| 00:03:27 |       |       |        |      |
|*  1 |  COUNT STOPKEY                         |                     |       |       |            |          |       |       |        |      |
|*  2 |   HASH JOIN                            |                     |     1 |   288 |  5273K  (1)| 00:03:27 |       |       |        |      |
|   3 |    JOIN FILTER CREATE                  | :BF0000             |     1 |    22 |    59   (0)| 00:00:01 |       |       |        |      |
|   4 |     PARTITION LIST ALL                 |                     |     1 |    22 |    59   (0)| 00:00:01 |     1 |     2 |        |      |
|   5 |      PARTITION RANGE ALL               |                     |     1 |    22 |    59   (0)| 00:00:01 |     1 |  LAST |        |      |
|   6 |       TABLE ACCESS BY LOCAL INDEX ROWID| ORDERS              |     1 |    22 |    59   (0)| 00:00:01 |     1 |    29 |        |      |
|*  7 |        INDEX RANGE SCAN                | IDX_ORDERS_CREATED  |     1 |       |    57   (0)| 00:00:01 |     1 |    29 |        |      |
|   8 |    VIEW                                | TEST                |  3840K|   974M|  5273K  (1)| 00:03:27 |       |       |        |      |
|   9 |     SORT GROUP BY                      |                     |  3840K|   201M|  5273K  (1)| 00:03:27 |       |       |        |      |
|  10 |      JOIN FILTER USE                   | :BF0000             |   994M|    50G|  5273K  (1)| 00:03:27 |       |       |        |      |
|  11 |       NESTED LOOPS                     |                     |   994M|    50G|  5273K  (1)| 00:03:27 |       |       |        |      |
|  12 |        INDEX FULL SCAN                 | PK_ID               |  3840K|    51M| 66212   (1)| 00:00:03 |       |       |        |      |
|* 13 |        INDEX STORAGE FAST FULL SCAN    | IDX_MN_AN_AD_ALL    |   259 | 10619 |     1   (0)| 00:00:01 |       |       |        |      |
|  14 |         REMOTE                         |                     |       |       |            |          |       |       |    DB2 | R->S |
----------------------------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):                                                                                           
---------------------------------------------------                                                                                           

   1 - filter(ROWNUM<10)                                                                                                                      
   2 - access("A_OUT"."ID"="Z_OUT"."ID")                                                                                                
   7 - access("A_OUT"."CREATED">TRUNC(SYSDATE@!))                                                                                      
  13 - filter("B2"."ATTR_1"=NVL(CASE  WHEN (SUBSTR("ID",(-1))<'5' AND  EXISTS (SELECT 0 FROM  "A1")) THEN 'YYY' END ,'#') OR               
              "B2"."ATTR_1"='*')                                                                                                              

Remote SQL Information (identified by operation id):                                                                                          
----------------------------------------------------                                                                                          

  14 - EXPLAIN PLAN INTO PLAN_TABLE@! FOR SELECT 0 FROM "DUAL" "A1" (accessing 'DB2' )                                                        

我希望该视图可以被访问n次,就像在第一种情况中一样。 我尝试使用提示,但没有成功。

可能有用的说法是,即使视图中没有注释and exists(select 1 from dual@db2)行,以下查询仍具有出色的性能(我知道这与Q1不同)。

select
    (select value from test z_out where a_out.id=z_out.id) as value,
    a_out.id
from orders a_out
where a_out.created>trunc(sysdate) and rownum<10

因此,我认为即使访问了n行,即使该视图and exists(select 1 from dual@db2)被访问了alter session set statistics_level = 'ALL'; -- Q1 (the query I'm having problems with) select * from table (dbms_xplan.display_cursor (format=>'ALLSTATS LAST')); Plan hash value: 3271081243 ------------------------------------------------------------------------------------------------------------------------------------------------------------ | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | OMem | 1Mem | Used-Mem | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | | 0 |00:00:00.01 | 0 | 0 | | | | |* 1 | COUNT STOPKEY | | 1 | | 0 |00:00:00.01 | 0 | 0 | | | | |* 2 | HASH JOIN | | 1 | 1 | 0 |00:00:00.01 | 0 | 0 | 3789K| 3789K| 1078K (0)| | 3 | JOIN FILTER CREATE | :BF0000 | 1 | 1 | 25602 |00:00:00.22 | 23345 | 161 | | | | | 4 | PARTITION LIST ALL | | 1 | 1 | 25602 |00:00:00.21 | 23345 | 161 | | | | | 5 | PARTITION RANGE ALL | | 2 | 1 | 25602 |00:00:00.21 | 23345 | 161 | | | | | 6 | TABLE ACCESS BY LOCAL INDEX ROWID| ORDERS | 29 | 1 | 25602 |00:00:00.20 | 23345 | 161 | | | | |* 7 | INDEX RANGE SCAN | IDX_CREATED | 13 | 1 | 25602 |00:00:00.12 | 474 | 161 | 1025K| 1025K| | | 8 | VIEW | TEST | 1 | 3820K| 0 |00:00:00.01 | 0 | 0 | | | | | 9 | SORT GROUP BY | | 1 | 3820K| 0 |00:00:00.01 | 0 | 0 | 73728 | 73728 | | | 10 | JOIN FILTER USE | :BF0000 | 1 | 989M| 106M|00:03:38.87 | 60M| 52960 | | | | | 11 | NESTED LOOPS | | 1 | 989M| 328M|00:03:04.11 | 60M| 52960 | | | | | 12 | INDEX FULL SCAN | PK_ID | 1 | 3820K| 1245K|00:00:21.04 | 200K| 52959 | 1025K| 1025K| | |* 13 | INDEX STORAGE FAST FULL SCAN | IDX_MN_AN_AD_ALL | 1245K| 259 | 328M|00:02:12.09 | 60M| 1 | 1025K| 1025K| | | 14 | REMOTE | | 1 | | 1 |00:00:00.01 | 0 | 0 | | | | ------------------------------------------------------------------------------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter(ROWNUM<10) 2 - access("A_OUT"."ID"="Z_OUT"."ID") 7 - access("A_OUT"."CREATED">TRUNC(SYSDATE@!)) 13 - filter(("B2"."ATTR_1"=NVL(CASE WHEN (SUBSTR("ID",(-1))<'5' AND IS NOT NULL) THEN 'YYY' END ,'#') OR "B2"."ATTR_1"='*')) 次,该视图仍然可以正常工作。但是我无法向那个方向强制执行计划。

如果有必要,我只想将它们添加到视图DDL中(如果可能),这样使用该视图的人就不必担心。

================================================ =================

编辑:执行以下操作:

Q1

注意:如果视图中的and exists(select 1 from dual@db2)未注释,则Q1的性能会阻止查询完成。要获取以前的执行计划,我必须更改会话,运行Q1,停止--and exists(select 1 from dual@db2)(大约4分钟后),然后计算计划。

以下执行计划是用相同的方式生成的,但是视图中的行Plan hash value: 2906430222 ----------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | ----------------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 9 |00:00:00.01 | 223 | |* 1 | COUNT STOPKEY | | 1 | | 9 |00:00:00.01 | 223 | | 2 | NESTED LOOPS | | 1 | 1 | 9 |00:00:00.01 | 223 | | 3 | PARTITION LIST ALL | | 1 | 1 | 9 |00:00:00.01 | 41 | | 4 | PARTITION RANGE ALL | | 1 | 1 | 9 |00:00:00.01 | 41 | | 5 | TABLE ACCESS BY LOCAL INDEX ROWID| ORDERS | 14 | 1 | 9 |00:00:00.01 | 41 | |* 6 | INDEX RANGE SCAN | IDX_CREATED | 12 | 1 | 9 |00:00:00.01 | 33 | | 7 | VIEW PUSHED PREDICATE | TEST | 9 | 1 | 9 |00:00:00.01 | 182 | |* 8 | FILTER | | 9 | | 9 |00:00:00.01 | 182 | | 9 | SORT AGGREGATE | | 9 | 1 | 9 |00:00:00.01 | 182 | | 10 | NESTED LOOPS | | 9 | 259 | 2376 |00:00:00.01 | 182 | |* 11 | INDEX UNIQUE SCAN | PK_ID | 9 | 1 | 9 |00:00:00.01 | 20 | |* 12 | INDEX STORAGE FAST FULL SCAN | IDX_MN_AN_AD_ALL | 9 | 259 | 2376 |00:00:00.01 | 162 | ----------------------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter(ROWNUM<10) 6 - access("A_OUT"."CREATED">TRUNC(SYSDATE@!)) 8 - filter(COUNT(*)>0) 11 - access("ID"="A_OUT"."ID") 12 - storage(("B2"."ATTR_1"=NVL(CASE WHEN SUBSTR("ID",(-1))<'5' THEN 'YYY' END ,'#') OR "B2"."ATTR_1"='*')) filter(("B2"."ATTR_1"=NVL(CASE WHEN SUBSTR("ID",(-1))<'5' THEN 'YYY' END ,'#') OR "B2"."ATTR_1"='*')) 被注释了(性能很好)。

import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Paper from '@material-ui/core/Paper';
import Typography from '@material-ui/core/Typography';

const useStyles = makeStyles(theme => ({
  root: {
    padding: theme.spacing(3, 2),
    height: 200,
    verticalAlign: 'middle'
  },
}));

function PaperSheet() {
  const classes = useStyles();

  return (
    <div>
      <Paper className={classes.root}>
        <Typography variant="h5" component="h3">
          This is a sheet of paper.
        </Typography>
        <Typography component="p">
          Paper can be used to build surface or other elements for your application.
        </Typography>
      </Paper>
    </div>
  );
}

export default PaperSheet;

0 个答案:

没有答案