彻底搞懂oracle的标量子查询

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                   b1
         2 a2                   b2
         3 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                   b1
         2 a2                   b2
         3 a3
         4 a4
         5 a5
         6 a6
         7 a7
         8 a8
         9 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                   b1
         2 a2                   b1
         3 a3
         4 a4
         5 a5
         6 a6
         7 a7
         8 a8
         9 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                   b1
         2 a2                   b1
         3 a3                   b1
         4 a4                   b1
         5 a5                   b1
         6 a6                   b1
         7 a7                   b1
         8 a8                   b1
         9 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 a1
         1 a2
         1 a3
         1 a4
         1 a5
         1 a6
         1 a7
         1 a8
         1 a9
9 rows selected.
SQL> select * from b;
        ID NAME
---------- --------------------
         1 b1
         2 b1
         3 b1
         4 b1
         5 b1
         6 b1
         7 b1
         8 b1
         9 b1
9 rows selected.
SQL> select a.*,(select name from b where b.id=a.id) from a;
        ID NAME                 (SELECTNAMEFROMBWHER
---------- -------------------- --------------------
         1 a1                   b1
         1 a2                   b1
         1 a3                   b1
         1 a4                   b1
         1 a5                   b1
         1 a6                   b1
         1 a7                   b1
         1 a8                   b1
         1 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> 
</pre><pre name="code" class="sql"><strong><span style="font-size:18px;">关联字段a.id全部为1,a表有9行,标量子查询相当于执行9次select name from b where b.id=1 ,oracle也不傻,starts=1,说明只执行了1次。
总结:
理想状态下,a.id为主键,没有重复值,那么a表返回多少行,b表就要被执行多少次。
特殊情况下,a.id的distinct值只有n个,那么b表只执行n次。</span></strong>


  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于 Oracle 标量子查询中的 `LISTAGG` 函数,可以考虑以下几种优化方法: 1. 确保索引的使用:确保子查询中涉及的表上有适当的索引,以加快数据检索速度。如果子查询使用了过滤条件,可以考虑在相关列上创建索引。 2. 限制结果集大小:如果子查询返回的结果集很大,可以考虑在子查询中添加适当的过滤条件,以限制结果集的大小。这可以减少 `LISTAGG` 函数处理的数据,提高性能。 3. 使用内联视图:将子查询转换为内联视图(Inline View),可以避免多次执行子查询,从而提高性能。内联视图可以通过 WITH 子句或者嵌套查询的方式实现。 4. 考虑使用分析函数:如果子查询中需要对数据进行排序、分组或其他复杂的操作,可以考虑使用分析函数(Analytic Functions)来替代 `LISTAGG` 函数。分析函数通常比标量子查询更高效。 5. 优化查询计划:使用合适的查询提示(Query Hints)或者调整查询语句的结构,以促使 Oracle 生成更优化的查询计划。可以通过 EXPLAIN PLAN、SQL Trace 或者 SQL Monitoring 等工具来分析和优化查询计划。 6. 考虑使用其他技术:如果标量子查询性能问题仍然存在,可以考虑使用其他技术来实现相同的功能,例如使用连接查询、临表或者其他编程方式。 请注意,优化标量子查询涉及到具体的数据模型、查询语句和数据库配置等因素,因此需要根据具体情况进行分析和调整。建议在进行任何优化操作之前,先进行性能测试和评估,以确保优化策略的有效性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值