【发布时间】: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 分钟。
- 为什么两者之间会有这样的差异,为什么没有在执行计划中捕获?
- 我的全表扫描是否正确应用了?如果不是,最好的提示是什么?
- 什么是最好的(最新的)书籍/文档/在线教程来提升我的 SQL 性能技能?到目前为止,我已经看到 Oracle 有一个性能开发健身房,还有一些书籍,如 Advanced Oracle SQL Tuning,看起来很有趣。
【问题讨论】:
-
你如何测量经过的时间?获取第一行所需的时间?还是获取最后一行的时间? Oracle 必须实现所有行(估计为 440 万行)才能在第二个查询中计算它们。在第一个查询中,Oracle 可以更快地开始向客户端发送行,但将所有结果发送到客户端可能需要 3 分钟以上。
-
哦,好的,所以 Oracle 在 3 秒内检索前 50 行并不意味着同时检索所有行。我很困惑,因为根据我的短暂经验,检索第一行所花费的时间通常比使用 select 语句创建表所用的时间略短(尽管差别不大)。
-
另外请记住,将输出写入屏幕是一个相对较慢的过程。简单地读取 10k 行并将它们写入屏幕通常比读取相同的 10k 行并在内部进行一些工作而没有屏幕输出需要更长的时间。这就是为什么重要的是要准确考虑如何测量时差,以及将苹果与苹果进行比较。
标签: sql oracle query-optimization