ITPub博客

首页 > 数据库 > Oracle > [20220121]开发不应该这样写sql2.txt

[20220121]开发不应该这样写sql2.txt

原创 Oracle 作者:lfree 时间:2022-01-21 15:55:37 0 删除 编辑

[20220121]开发不应该这样写sql2.txt

--//生产系统遇到的优化问题,原始语句很复杂,在测试环境做一个分析并记录.

1.环境:
SCOTT@book> @ver1
PORT_STRING                    VERSION        BANNER
------------------------------ -------------- --------------------------------------------------------------------------------
x86_64/Linux 2.4.xx            11.2.0.4.0     Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

2.测试例子:
SCOTT@book> variable a number ;
SCOTT@book> exec :a := 7499;
PL/SQL procedure successfully completed.

SCOTT@book> @ sl all
alter session set statistics_level = all;
Session altered.

SCOTT@book> select * from emp where empno = :a or :a =0 ;
     EMPNO ENAME      JOB              MGR HIREDATE                   SAL       COMM     DEPTNO
---------- ---------- --------- ---------- ------------------- ---------- ---------- ----------
      7499 ALLEN      SALESMAN        7698 1981-02-20 00:00:00       1600        300         30

SCOTT@book> @ dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  b1b1d5k0f6had, child number 0
-------------------------------------
select * from emp where empno = :a or :a =0
Plan hash value: 3956160932
-----------------------------------------------------------------------------------------------------------------------------
| Id  | Operation         | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers | Reads  |
-----------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |      1 |        |       |     3 (100)|          |      1 |00:00:00.01 |       7 |      5 |
|*  1 |  TABLE ACCESS FULL| EMP  |      1 |      1 |    39 |     3   (0)| 00:00:01 |      1 |00:00:00.01 |       7 |      5 |
-----------------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$1 / EMP@SEL$1
Peeked Binds (identified by position):
--------------------------------------
   1 - (NUMBER): 7499
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(("EMPNO"=:A OR :A=0))

--//开发本意是这样可以实现带入0的时候使用全表扫描,而带入大于0的情况下选择索引,可是可是oracle的优化器没有这么智能,不知道开发的想法.
--//好久不做这类优化了,你可以测试单独使用USE_CONCAT提示无效.
select  /*+ USE_CONCAT(@"SEL$1") */ * from emp where (empno = :a or :a =0);
select  /*+ USE_CONCAT */ * from emp where (empno = :a or :a =0);

--//提示无效,大家可以看看很久以前的测试,链接:
--//http://blog.itpub.net/267265/viewspace-1788598/ =>[20150901]提示USE_CONCAT.txt

--//必须写成如下:
--//select  /*+ USE_CONCAT(@"SEL$1"  OR_PREDICATES(1)) */ * from emp where (empno = :a or :a =0);
--//select  /*+ USE_CONCAT(@"SEL$1" 8 OR_PREDICATES(1)) */ * from emp where (empno = :a or :a =0);

SCOTT@book> select  /*+ USE_CONCAT(@"SEL$1" 8 OR_PREDICATES(1)) */ * from emp where (empno = :a or :a =0);
     EMPNO ENAME      JOB              MGR HIREDATE                   SAL       COMM     DEPTNO
---------- ---------- --------- ---------- ------------------- ---------- ---------- ----------
      7499 ALLEN      SALESMAN        7698 1981-02-20 00:00:00       1600        300         30

SCOTT@book> @ dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  64amtw9gz3kry, child number 0
-------------------------------------
select  /*+ USE_CONCAT(@"SEL$1" 8 OR_PREDICATES(1)) */ * from emp where
(empno = :a or :a =0)
Plan hash value: 3475259919
----------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                     | Name   | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |
----------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT              |        |      1 |        |       |     4 (100)|          |      1 |00:00:00.01 |       2 |
|   1 |  CONCATENATION                |        |      1 |        |       |            |          |      1 |00:00:00.01 |       2 |
|*  2 |   FILTER                      |        |      1 |        |       |            |          |      0 |00:00:00.01 |       0 |
|   3 |    TABLE ACCESS FULL          | EMP    |      0 |     14 |   546 |     3   (0)| 00:00:01 |      0 |00:00:00.01 |       0 |
|*  4 |   FILTER                      |        |      1 |        |       |            |          |      1 |00:00:00.01 |       2 |
|   5 |    TABLE ACCESS BY INDEX ROWID| EMP    |      1 |      1 |    39 |     1   (0)| 00:00:01 |      1 |00:00:00.01 |       2 |
|*  6 |     INDEX UNIQUE SCAN         | PK_EMP |      1 |      1 |       |     0   (0)|          |      1 |00:00:00.01 |       1 |
----------------------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$1
   3 - SEL$1_1 / EMP@SEL$1
   5 - SEL$1_2 / EMP@SEL$1_2
   6 - SEL$1_2 / EMP@SEL$1_2
Peeked Binds (identified by position):
--------------------------------------
   1 - (NUMBER): 7499
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter(:A=0)
   4 - filter(LNNVL(:A=0))
   6 - access("EMPNO"=:A)

--//少量出现可以使用sql profile之类稳定执行计划,但是如果多次出现使用sql profile就很麻烦,建议开发不要在应该中使用这样的编写sql模式.
--//或者称为技巧.加入判断来构件sql 语句.

--//我真心很奇怪,在exadata上要7秒才能完成的语句,开发居然也把它上线,不仔细看看吗?
> @dashtop sql_id,event sql_id='ay987w0c6r8rv'  sysdate-4 sysdate-1
    Total
  Seconds     AAS %This   SQL_ID        EVENT                                      FIRST_SEEN          LAST_SEEN
--------- ------- ------- ------------- ------------------------------------------ ------------------- -------------------
    17420      .1   64%   ay987w0c6r8rv                                            2022-01-17 19:54:09 2022-01-18 20:30:46
     9520      .0   35%   ay987w0c6r8rv cell smart table scan                      2022-01-17 19:42:21 2022-01-18 20:29:05
       40      .0    0%   ay987w0c6r8rv enq: KO - fast object checkpoint           2022-01-18 11:12:51 2022-01-18 19:40:50
       40      .0    0%   ay987w0c6r8rv gc cr block 2-way                          2022-01-18 11:08:48 2022-01-18 15:56:37
       20      .0    0%   ay987w0c6r8rv reliable message                           2022-01-18 11:03:23 2022-01-18 11:28:34






来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/267265/viewspace-2853429/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
熟悉oracle相关技术,擅长sql优化,rman备份与恢复,熟悉linux shell编程。

注册时间:2008-01-03

  • 博文量
    4006
  • 访问量
    7969436