当前位置: 首页 > news >正文

标量子查询 外表有多少重复值决定filter次数 转化 left join

1. 标量子查询的执行计划
SORT  和 Table 是齐平的,上面没有类似HASH JOIN之类的连接方式。

2. 外表驱动内表的时候 starts 代表执行次数,由内表的distinct值决定的,相当于内表做了一个view

3. 内表做的view,可以直接和外表做外链接,这样可以改为join,12C 后可以自动转化了。

---------标量子查询  case when 用  left join 的改写-----

 --Oracle标量子查询执行计划,性能为王:SQL标量子查询的优化案例分析-CSDN博客
       SELECT 
       CASE    WHEN OFFER_SPEC_ID IN      ----A的distinct   OFFER_SPEC_ID 值决定循环次数 
              (SELECT LOCAL_ITEM_CODE    FROM PU_meta_DIM.CODE_ITEM                      
                      WHERe PROV_TYPE_ID = 49AND PROV_ITEM_ID = 64 改写成view 
)          
          THEN   1    ELSE    0 END
 FROM PU_base_IND.DM_SP_SUB_OFFER_SERV_D_201407       
 PARTITION(P20140727) A
 WHERe LOCAL_CODE = '028'      

SELECT 
CASE WHEN a.OFFER_SPEC_ID = b.LOCAL_ITEM_CODE THEN 1 ELSE 0 END
 FROM PU_base_IND.DM_SP_SUB_OFFER_SERV_D_201407 PARTITION (P20140727) A,
(SELECt DISTINCT LOCAL_ITEM_CODE
FROM PU_meta_DIM.CODE_ITEM
WHERe PROV_TYPE_ID = 49 AND PROV_ITEM_ID = 64) b

AND a.OFFER_SPEC_ID = b.LOCAL_ITEM_CODE(+ )
AND TO_CHAr (a.OFFER_SPEC_ID) = c.OFFER_SPEC_ID(+ )
AND TO_CHAr (a.OFFER_SPEC_ID) = d.OFFER_SPEC_ID(+ )
AND TO_CHAr (a.OFFER_SPEC_ID) = e.LOCAL_ITEM_CODE(+ )  

量子查询特点及特殊执行计划

1.1 量子查询执行计划

1)标量子查询的计划和普通计划的执行顺序不同,执行计划中标量子查询虽然在上面,但是它由下面的节点驱动,每行驱动查询一次标量子查询,而普通执行计划是下面的节点受上面节点驱动。(具体见下面示例分析)

2)标量子查询和FILTER类似,如果是它们引起的性能问题,要重点关注是否是执行子查询的次数过多导致查询的效率不高。3)标量子查询和FILTER类似,它会根据输入和输出构建HASH表缓存键值对,已经查询过的键值对直接从缓存中查找,不用再次执行子查询,从而减少子查询的次数达到优化的目的,10g和11g缓存的是255个HASH BUCKETS,12C是1024个HASH BUCKETS。如下所示:

从上面可以看出,标量子查询执行计划和普通执行计划不一样,它上面节点的是被下面节点驱动的,类似FILTER,谓词部分有系统绑定变量:B1,本例中ID 1-9属于标量子查询部分,它由ID=10的节点驱动,ID=10的结果集影响ID 1-9标量子查询的执行次数,标量子查询执行次数还和缓存有关,也就是ID=10的关联条件CUST_ID的DISTINCT数目。

下面探讨下标量子查询特点以及优化方法,对标量子查询的优化首选方式就是改写。

1.2 标量子查询特点

子查询执行次数依赖于关键条件DISTINCT数目,重复值越多,效率越好,反之,效率差。

如下所示:

从上面执行计划可以看出,虽然驱动的A-ROWS有108K行,但是因为distinct数目是11,实际上标量子查询只执行11次,由此可以看出,ORACLE内部构建了缓存存储键值对,从而减少子查询执行次数,达到优化目的。

2

标量子查询优化方法

标量子查询的改写:减少标量子查询次数、改为外连接使用JOIN。

2.1 减少子查询执行次数

2.2 将标量子查询改为外连接

其中改为外连接也是12C对标量子查询优化的新特性。

3

12C标量子查询优化新特性 

如前面所示,在12c之前,对于scalary subquery是无法unnest的,这样就导致标量子查询的执行次数受驱动表行数的影响,类似FILTER操作,而且scalary subquery的执行计划和普通执行计划不一样。

select dname,       (select max(b.sal) from scott.emp b where b.deptno = a.deptno)  from scott.dept a;

12C对标量子查询的优化如下:

  

12C优化改进其实将标量子查询内部改成OUTER JOIN,从而充分利用JOIN算法进行优化提高效率,注意12C针对标量子查询的优化只对于max,min,avg单个有效(类似max||min等组合的无效),对count、查询列等无效,并且受参数_optimizer_unnest_scalar_sq控制。

----------------------

oracle标量子查询和自己定义函数有时用起来比較方便,并且开发者也常常使用。数据量小还无所谓。数据量大,往往存在性能问题。

下面測试帮助大家彻底搞懂标量子查询。 SQL> create table a (id int,name varchar2(10)); Table created. SQL> create table b (id int,name varchar2(10)); Table created. SQL> insert into a values (1,'a1'); 1 row created. SQL> insert into a values (2,'a2'); 1 row created. SQL> insert into b values (1,'b1'); 1 row created. SQL> insert into b values (2,'b2'); 1 row created. SQL> commit; Commit complete. SQL> @getlvall Session altered. SQL> select a.*,(select name from b where b.id=a.id) from a; ID NAME (SELECTNAMEFROMBWHER ---------- -------------------- -------------------- 1 a1 b1 2 a2 b2 SQL> @getplanspe PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- SQL_ID 8rv825dykpx1m, child number 0 ------------------------------------- select a.*,(select name from b where b.id=a.id) from a Plan hash value: 2657529235 ------------------------------------------------------------------------------------ | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | ------------------------------------------------------------------------------------ |* 1 | TABLE ACCESS FULL| B | 2 | 1 | 2 |00:00:00.01 | 14 | | 2 | TABLE ACCESS FULL| A | 1 | 2 | 2 |00:00:00.01 | 8 | ------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("B"."ID"=:B1) Note ----- - dynamic sampling used for this statement 22 rows selected.

复制

<strong>--由上面的运行计划能够知道,b表运行2次。返回2行</strong>
SQL> insert into a values (3,'a3');
1 row created.
SQL> commit;
Commit complete.
SQL> select a.*,(select name from b where b.id=a.id) from a;ID NAME                 (SELECTNAMEFROMBWHER
---------- -------------------- --------------------1 a1                   b12 a2                   b23 a3
SQL> @getplanspe
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  8rv825dykpx1m, child number 0
-------------------------------------
select a.*,(select name from b where b.id=a.id) from a
Plan hash value: 2657529235
------------------------------------------------------------------------------------
| Id  | Operation         | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
------------------------------------------------------------------------------------
|*  1 |  TABLE ACCESS FULL| B    |      3 |      1 |      2 |00:00:00.01 |      21 |
|   2 |  TABLE ACCESS FULL| A    |      1 |      2 |      3 |00:00:00.01 |       8 |
------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------1 - filter("B"."ID"=:B1)
Note
------ dynamic sampling used for this statement
22 rows selected.
<strong>--由上面的运行计划能够知道,b表运行3次。返回2行</strong>
SQL> insert into a values (4,'a4');
1 row created.
SQL> insert into a values (5,'a5');
1 row created.
SQL> insert into a values (6,'a6');
1 row created.
SQL> insert into a values (7,'a7');
1 row created.
SQL> insert into a values (8,'a8');
1 row created.
SQL> insert into a values (9,'a9');
1 row created.
SQL> commit;
Commit complete.
SQL> select a.*,(select name from b where b.id=a.id) from a;ID NAME                 (SELECTNAMEFROMBWHER
---------- -------------------- --------------------1 a1                   b12 a2                   b23 a34 a45 a56 a67 a78 a89 a9
9 rows selected.
SQL> @getplanspe
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  8rv825dykpx1m, child number 0
-------------------------------------
select a.*,(select name from b where b.id=a.id) from a
Plan hash value: 2657529235
------------------------------------------------------------------------------------
| Id  | Operation         | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
------------------------------------------------------------------------------------
|*  1 |  TABLE ACCESS FULL| B    |      9 |      1 |      2 |00:00:00.01 |      63 |
|   2 |  TABLE ACCESS FULL| A    |      1 |      2 |      9 |00:00:00.01 |       8 |
------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------1 - filter("B"."ID"=:B1)
Note
------ dynamic sampling used for this statement
22 rows selected.
<strong>
--由上面的运行计划能够知道,b表运行9次,返回2行</strong>
SQL> update b set name='b1';
2 rows updated.
SQL> commit;
Commit complete.
SQL> select a.*,(select name from b where b.id=a.id) from a;ID NAME                 (SELECTNAMEFROMBWHER
---------- -------------------- --------------------1 a1                   b12 a2                   b13 a34 a45 a56 a67 a78 a89 a9
9 rows selected.
SQL> @getplanspe
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  8rv825dykpx1m, child number 0
-------------------------------------
select a.*,(select name from b where b.id=a.id) from a
Plan hash value: 2657529235
------------------------------------------------------------------------------------
| Id  | Operation         | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
------------------------------------------------------------------------------------
|*  1 |  TABLE ACCESS FULL| B    |      9 |      1 |      2 |00:00:00.01 |      63 |
|   2 |  TABLE ACCESS FULL| A    |      1 |      2 |      9 |00:00:00.01 |       8 |
------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------1 - filter("B"."ID"=:B1)
Note
------ dynamic sampling used for this statement
22 rows selected.
<strong>--由上面的运行计划能够知道,b表运行2次,返回2行</strong>  原作者这里应该错了
SQL> insert into b values (3,'b1');
1 row created.
SQL> insert into b values (4,'b1');
1 row created.
SQL> insert into b values (5,'b1');
1 row created.
insert into b values (6,'b1');b1');
1 row created.
SQL> insert into b values (7,'b1');
1 row created.
SQL> insert into b values (8,'b1');
1 row created.
SQL> insert into b values (9,'b1');
1 row created.
SQL> commit;
Commit complete.
SQL> select a.*,(select name from b where b.id=a.id) from a;ID NAME                 (SELECTNAMEFROMBWHER
---------- -------------------- --------------------1 a1                   b12 a2                   b13 a3                   b14 a4                   b15 a5                   b16 a6                   b17 a7                   b18 a8                   b19 a9                   b1
9 rows selected.
SQL> @getplanspe
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  8rv825dykpx1m, child number 0
-------------------------------------
select a.*,(select name from b where b.id=a.id) from a
Plan hash value: 2657529235
------------------------------------------------------------------------------------
| Id  | Operation         | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
------------------------------------------------------------------------------------
|*  1 |  TABLE ACCESS FULL| B    |      9 |      1 |      9 |00:00:00.01 |      63 |
|   2 |  TABLE ACCESS FULL| A    |      1 |      2 |      9 |00:00:00.01 |       8 |
------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------1 - filter("B"."ID"=:B1)
Note
------ dynamic sampling used for this statement
22 rows selected.
<strong>--b.name字段所有为‘b1’。由上面的运行计划能够知道。b表运行9次。返回9行</strong>
SQL> update a set id=1;
9 rows updated.
SQL> commit;
Commit complete.
SQL> select * from a;ID NAME
---------- --------------------1 a11 a21 a31 a41 a51 a61 a71 a81 a9
9 rows selected.
SQL> select * from b;ID NAME
---------- --------------------1 b12 b13 b14 b15 b16 b17 b18 b19 b1
9 rows selected.
SQL> select a.*,(select name from b where b.id=a.id) from a;ID NAME                 (SELECTNAMEFROMBWHER
---------- -------------------- --------------------1 a1                   b11 a2                   b11 a3                   b11 a4                   b11 a5                   b11 a6                   b11 a7                   b11 a8                   b11 a9                   b1
9 rows selected.
SQL> @getplanspe
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  8rv825dykpx1m, child number 0
-------------------------------------
select a.*,(select name from b where b.id=a.id) from a
Plan hash value: 2657529235
------------------------------------------------------------------------------------
| Id  | Operation         | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
------------------------------------------------------------------------------------
|*  1 |  TABLE ACCESS FULL| B    |      1 |      1 |      1 |00:00:00.01 |       7 |
|   2 |  TABLE ACCESS FULL| A    |      1 |      2 |      9 |00:00:00.01 |       8 |
------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------1 - filter("B"."ID"=:B1)
Note
------ dynamic sampling used for this statement
22 rows selected.
SQL> 
关联字段a.id所有为1。a表有9行,标量子查询相当于运行9次select name from b where b.id=1 ,oracle也不傻,starts=1。说明仅仅运行了1次。

所以是看外表有多少重复值决定filter次数的,和内表重复值无关。

http://www.dtcms.com/a/304932.html

相关文章:

  • Python三大Web框架:FastAPI vs Flask vs Django 详解与快速入门指南
  • BreachForums 黑客论坛强势回归
  • windows软件ARM64和AMD64(x64)区别,如何查看电脑支持哪种
  • JVM易混淆名称
  • 大型微服务项目:听书——多端重复提交订单问题适配器模式实现不同支付方式的选择零钱支付逻辑
  • 爬虫逆向之瑞数五案例:某某医学院(补环境,联调)
  • 适配器模式的三种C++实现
  • 宠物经济行业研究系列报告
  • electron-vite 动态加载脚本 实现动态插件
  • 如何为你的WordPress网站选择合适的安全插件
  • 【效率工具】255款工作计划表格Excel电子版模板:总结日月周报日历安排提醒时间管理
  • 遍历-找到匹配的节点
  • 零基础-动手学深度学习-7.6. 残差网络(ResNet)
  • [leetcode] 子集
  • OpenCL - study - code04 canny
  • 泰勒图中RMSD和RMSE是一个指标吗?
  • 掌控AI工具链:用 Python + API 构建 AI MCP 服务器
  • VUE进阶案例
  • Apple: A Legendary Journey of Innovation, Business, and Global Influence
  • [SWPU2019]Web1
  • VxWorks入门 【VxWorks程序运行】六
  • 数据库表的运算及表示方法
  • jQuery DOM 遍历详解
  • docker技术框架
  • 2024年蓝桥杯Scratch10月图形化stema选拔赛真题——旋转的图形
  • Luogu P2577 午餐(ZJOI2004)
  • 市政道路积水监测系统:守护城市雨天出行安全的 “智慧防线”
  • iOS仿写 —— 计算器
  • 前端代码格式化工具HTML离线版
  • redhat7.9更换源为centos7(阿里云源-目前centos7可用的源)