【问题标题】:Oracle SQL Execution Plan DifferenceOracle SQL 执行计划差异
【发布时间】:2021-06-16 17:19:38
【问题描述】:

我有以下查询,我正在为它生成执行计划:

(编辑:我正在使用 SQL Developer)。

EXPLAIN PLAN
    FOR
WITH aux AS (
    SELECT
        *
    FROM
        cdc.uap_fkkvkp@rbip
    WHERE
        ezawe = 'D'
)
SELECT /* FULL(a) FULL(b) */
--    COUNT(1)
    b.zzpayment_plan,
    b.vkont,
    b.gpart,
    a.opbel,
    a.opupw,
    a.opupk,
    a.opupz,
    a.blart,
    a.betrw
FROM
    cdc.uap_dfkkop@rbip   a
    JOIN aux                   b ON b.vkont = a.vkont
WHERE
    a.augst IS NULL
    AND a.xanza IS NULL
    AND a.stakz IS NULL
    AND a.augrs IS NULL
    AND a.abwtp IS NULL;
    
SELECT
    *
FROM
    TABLE ( dbms_xplan.display );

它给出了以下计划:

Plan hash value: 289441478
 
-----------------------------------------------------------------------------------------------------------------------
| Id  | Operation                            | Name                   | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                     |                        |  4404K|   634M|       |  6752K  (1)| 00:04:24 |
|*  1 |  HASH JOIN                           |                        |  4404K|   634M|   291M|  6752K  (1)| 00:04:24 |
|*  2 |   TABLE ACCESS STORAGE FULL          | UAP_FKKVKP             |  4487K|   239M|       |   559K  (1)| 00:00:22 |
|*  3 |   TABLE ACCESS BY INDEX ROWID BATCHED| UAP_DFKKOP             |  4404K|   399M|       |  6160K  (1)| 00:04:01 |
|   4 |    BITMAP CONVERSION TO ROWIDS       |                        |       |       |       |            |          |
|   5 |     BITMAP AND                       |                        |       |       |       |            |          |
|*  6 |      BITMAP INDEX SINGLE VALUE       | UAP_DFKKOP_AUGST_2     |       |       |       |            |          |
|*  7 |      BITMAP INDEX SINGLE VALUE       | UAP_DFKKOP_NEW_STAKZ_2 |       |       |       |            |          |
|*  8 |      BITMAP INDEX SINGLE VALUE       | UAP_DFKKOP_AUGRS_2     |       |       |       |            |          |
-----------------------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - access("UAP_FKKVKP"."VKONT"="A"."VKONT")
   2 - storage("EZAWE"=U'D')
       filter("EZAWE"=U'D')
   3 - filter("A"."XANZA" IS NULL AND "A"."ABWTP" IS NULL)
   6 - access("A"."AUGST" IS NULL)
   7 - access("A"."STAKZ" IS NULL)
   8 - access("A"."AUGRS" IS NULL)
 
Note
-----
   - dynamic statistics used: dynamic sampling (level=2)
   - 1 Sql Plan Directive used for this statement

但是,如果我为代码的第一部分生成计划,但对于 COUNT(1) 未注释(以及其他选项已注释),则显示如下(与之前的执行计划完全相同):

Plan hash value: 2732266276
 
------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                             | Name                   | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                      |                        |     1 |    66 |       |  6736K  (1)| 00:04:24 |
|   1 |  SORT AGGREGATE                       |                        |     1 |    66 |       |            |          |
|*  2 |   HASH JOIN                           |                        |  4404K|   277M|   171M|  6736K  (1)| 00:04:24 |
|*  3 |    TABLE ACCESS STORAGE FULL          | UAP_FKKVKP             |  4487K|   119M|       |   559K  (1)| 00:00:22 |
|*  4 |    TABLE ACCESS BY INDEX ROWID BATCHED| UAP_DFKKOP             |  4404K|   159M|       |  6160K  (1)| 00:04:01 |
|   5 |     BITMAP CONVERSION TO ROWIDS       |                        |       |       |       |            |          |
|   6 |      BITMAP AND                       |                        |       |       |       |            |          |
|*  7 |       BITMAP INDEX SINGLE VALUE       | UAP_DFKKOP_AUGST_2     |       |       |       |            |          |
|*  8 |       BITMAP INDEX SINGLE VALUE       | UAP_DFKKOP_NEW_STAKZ_2 |       |       |       |            |          |
|*  9 |       BITMAP INDEX SINGLE VALUE       | UAP_DFKKOP_AUGRS_2     |       |       |       |            |          |
------------------------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - access("UAP_FKKVKP"."VKONT"="A"."VKONT")
   3 - storage("EZAWE"=U'D')
       filter("EZAWE"=U'D')
   4 - filter("A"."XANZA" IS NULL AND "A"."ABWTP" IS NULL)
   7 - access("A"."AUGST" IS NULL)
   8 - access("A"."STAKZ" IS NULL)
   9 - access("A"."AUGRS" IS NULL)
 
Note
-----
   - dynamic statistics used: dynamic sampling (level=2)
   - 1 Sql Plan Directive used for this statement

如果我尝试执行这两个查询,第一个大约需要 3 秒,而第二个大约需要 8 分钟。

  1. 为什么两者之间会有这样的差异,为什么没有在执行计划中捕获?
  2. 我的全表扫描是否正确应用了?如果不是,最好的提示是什么?
  3. 什么是最好的(最新的)书籍/文档/在线教程来提升我的 SQL 性能技能?到目前为止,我已经看到 Oracle 有一个性能开发健身房,还有一些书籍,如 Advanced Oracle SQL Tuning,看起来很有趣。

【问题讨论】:

  • 你如何测量经过的时间?获取第一行所需的时间?还是获取最后一行的时间? Oracle 必须实现所有行(估计为 440 万行)才能在第二个查询中计算它们。在第一个查询中,Oracle 可以更快地开始向客户端发送行,但将所有结果发送到客户端可能需要 3 分钟以上。
  • 哦,好的,所以 Oracle 在 3 秒内检索前 50 行并不意味着同时检索所有行。我很困惑,因为根据我的短暂经验,检索第一行所花费的时间通常比使用 select 语句创建表所用的时间略短(尽管差别不大)。
  • 另外请记住,将输出写入屏幕是一个相对较慢的过程。简单地读取 10k 行并将它们写入屏幕通常比读取相同的 10k 行并在内部进行一些工作而没有屏幕输出需要更长的时间。这就是为什么重要的是要准确考虑如何测量时差,以及将苹果与苹果进行比较。

标签: sql oracle query-optimization


【解决方案1】:

有了解释就没有真正的执行。在会话级别将 statistics_level 设置为 ALL 后,您将收到更多关于实际执行的详细信息。 但是在 SQLPLUS 中运行它:

set serverout off
alter session set statistics_level=all;

<execute the query here without explain>

select * from table(dbms_xplan.display_cursor(null,null,'RUNSTATS_LAST')); 

如果您提供两个这样的计划而不是 EXPLAIN PLAN,那么您的读者会更容易。 重要列的简短描述(Tanel Poder 网站不错):

Starts - number of execution of the step
A-Rows - actual number of rows received from this step
Buffers - number of reads from RAM - you have to decrease this value
Reads - number of reads from disk
Writes - number of writes to disk - different from 0 - mainly for SELECTs when TEMP is used 

此计划使用方法示例如下:https://tanelpoder.com/files/Oracle_SQL_Plan_Execution.pdf

【讨论】:

  • 即使我的一个查询(没有提示的查询)永远运行,我有没有办法做到这一点?
  • 可以,如果运行时间长,可以按CTRL+C停止,然后查看计划。
  • 是否会显示与未选中“获取所有行”复选框相同的结果?
猜你喜欢
  • 2012-03-14
  • 2011-02-10
  • 2018-07-13
  • 1970-01-01
  • 2014-10-19
  • 1970-01-01
  • 2012-03-07
  • 2012-09-02
  • 1970-01-01
相关资源
最近更新 更多