测试崖山是否支持优化器各种消除技术

为什么要写本篇文章?先来看个案例吧

2012年还是2013具体记不清楚了,某运营商,Oracle10gR2

复制代码
select count(*) from a left join b on a.id=b.id;

a和b上千万行数据,a.id,b.id都是主键,SQL跑12秒。因为b.id是主键,a left join b不管有没有关联上,最终返回的数据始终是a的总行数,所以当时把SQL改写为:

复制代码
select count(*) from a;

最终0.05秒就能返回结果(到了Oracle11g之后,CBO会自动改写上面SQL,去掉b)

我到现在还记得当时优化完这条SQL之后,我得了500块奖励,开发被扣了500块,并且被屌了一顿。

最近几年也做了大量的去O项目,数据库以openGauss系为主,遇到了下面问题:

1.ORDER BY消除问题,

2.DISTINCT/UNIQUE消除问题

3.LEFT JOIN 分析函数,标量子查询,自定义函数消除问题

后来随着数据库内核版本迭代,上面问题基本上都解决了。

现在来测试崖山是否支持上面提到的各种消除技术(其他国产数据库懒得测试了,篇幅不允许)

数据库版本:yashan23.5.1

dept和emp表来自Oracle11g SCOTT示例账户,dept.deptno列是主键,emp.empno列是主键,emp.deptno列是外键,引用dept.deptno

TEST02数据来自DBA_OBJECTS,共8w行数据

TEST01数据来自TEST02,重复512次,共4500W行

TEST02,TEST01不创建索引

1.ORDER BY 消除

复制代码
select count(*) from (select * from emp order by empno);

Oracle

复制代码
SQL> select count(*) from (select * from emp order by empno);

Elapsed: 00:00:00.00

Execution Plan
----------------------------------------------------------
Plan hash value: 2937609675

-------------------------------------------------------------------
| Id  | Operation        | Name   | Rows  | Cost (%CPU)| Time     |
-------------------------------------------------------------------
|   0 | SELECT STATEMENT |        |     1 |     1   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE  |        |     1 |            |          |
|   2 |   INDEX FULL SCAN| PK_EMP |    14 |     1   (0)| 00:00:01 |
-------------------------------------------------------------------

yashan

复制代码
SQL> select count(*) from (select * from emp order by empno);

Execution Plan                                                   
---------------------------------------------------------------- 
SQL hash value: 65278406                                        
Optimizer: ADOPT_C                                              
                                                                
+----+--------------------------------+----------------------+------------+----------+----------+-------------+----------+----------+----------+----------+--------------------------------+
| Id | Operation type                 | Name                 | Owner      | E - Rows | A - Rows | Cost(%CPU)  | A - Time | Loops    | Memory   | Disk     | Partition info                 |
+----+--------------------------------+----------------------+------------+----------+----------+-------------+----------+----------+----------+----------+--------------------------------+
|  0 | SELECT STATEMENT               |                      |            |          |         1|             |        34|         2|         0|         0|                                |
|  1 |  AGGREGATE                     |                      |            |         1|         1|        1( 0)|        32|         2|         0|         0|                                |
|  2 |   VIEW                         |                      |            |        14|        14|        1( 0)|        30|        15|         0|         0|                                |
|  3 |    INDEX FAST FULL SCAN        | PK_EMP               | SCOTT      |        14|        14|        1( 0)|        27|        15|         0|         0|                                |
+----+--------------------------------+----------------------+------------+----------+----------+-------------+----------+----------+----------+----------+--------------------------------+

Statistics
----------------------------------------------------------------------------------------------------
                    0 physical reads                                                  
                    7 db block gets                                                   
                    0 consistent gets                                                 
                    0 redo size                                                       
                    0 recursive calls                                                 
                    0 bytes sent via SQL*Net to client                                
                    0 bytes received via SQL*Net from client                          
                    0 SQL*Net roundtrips to/from client                               
                    0 sorts (memory)                                                  
                    0 sorts (disk)                                                    
                    1 rows processed                                                  
                    0 bytes sent via PX                                               
                    0 block received                                                  

24 rows fetched.

Elapsed: 00:00:00.011

结论:崖山支持ORDER BY消除

2.单表DISTINCT消除

复制代码
select distinct * from emp;

Oracle

复制代码
SQL> select distinct * from emp;

14 rows selected.

Elapsed: 00:00:00.00

Execution Plan
----------------------------------------------------------
Plan hash value: 3956160932

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |    14 |   532 |     3   (0)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| EMP  |    14 |   532 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------

yashan

复制代码
SQL> select distinct * from emp;

Execution Plan                                                   
---------------------------------------------------------------- 
SQL hash value: 3454160452                                      
Optimizer: ADOPT_C                                              
                                                                
+----+--------------------------------+----------------------+------------+----------+----------+-------------+----------+----------+----------+----------+--------------------------------+
| Id | Operation type                 | Name                 | Owner      | E - Rows | A - Rows | Cost(%CPU)  | A - Time | Loops    | Memory   | Disk     | Partition info                 |
+----+--------------------------------+----------------------+------------+----------+----------+-------------+----------+----------+----------+----------+--------------------------------+
|  0 | SELECT STATEMENT               |                      |            |          |        14|             |        10|        15|         0|         0|                                |
|  1 |  TABLE ACCESS FULL             | EMP                  | SCOTT      |        14|        14|        1( 0)|         9|        15|         0|         0|                                |
+----+--------------------------------+----------------------+------------+----------+----------+-------------+----------+----------+----------+----------+--------------------------------+

Statistics
----------------------------------------------------------------------------------------------------
                    0 physical reads                                                  
                    7 db block gets                                                   
                    0 consistent gets                                                 
                    0 redo size                                                       
                    0 recursive calls                                                 
                    0 bytes sent via SQL*Net to client                                
                    0 bytes received via SQL*Net from client                          
                    0 SQL*Net roundtrips to/from client                               
                    0 sorts (memory)                                                  
                    0 sorts (disk)                                                    
                   14 rows processed                                                  
                    0 bytes sent via PX                                               
                    0 block received                                                  

22 rows fetched.

Elapsed: 00:00:00.004

结论:崖山支持单表DISTINCT消除

3.标量子查询消除

复制代码
select count(*)
  from (select a.*,
               (select count(*) from test01 b where a.object_id = b.object_id) cnt
          from test02 a);

Oracle

复制代码
SQL> select count(*)
  2    from (select a.*,
  3                 (select count(*) from test01 b where a.object_id = b.object_id) cnt
  4            from test02 a);

Elapsed: 00:00:00.00

Execution Plan
----------------------------------------------------------
Plan hash value: 322432667

---------------------------------------------------------------------
| Id  | Operation          | Name   | Rows  | Cost (%CPU)| Time     |
---------------------------------------------------------------------
|   0 | SELECT STATEMENT   |        |     1 |   347   (1)| 00:00:01 |
|   1 |  SORT AGGREGATE    |        |     1 |            |          |
|   2 |   TABLE ACCESS FULL| TEST02 | 86987 |   347   (1)| 00:00:01 |
---------------------------------------------------------------------

yashan

复制代码
SQL> select count(*)
  from (select a.*,
               (select count(*) from test01 b where a.object_id = b.object_id) cnt
          from test02 a);   2    3    4 

Execution Plan                                                   
---------------------------------------------------------------- 
SQL hash value: 232128976                                       
Optimizer: ADOPT_C                                              
                                                                
+----+--------------------------------+----------------------+------------+----------+----------+-------------+----------+----------+----------+----------+--------------------------------+
| Id | Operation type                 | Name                 | Owner      | E - Rows | A - Rows | Cost(%CPU)  | A - Time | Loops    | Memory   | Disk     | Partition info                 |
+----+--------------------------------+----------------------+------------+----------+----------+-------------+----------+----------+----------+----------+--------------------------------+
|  0 | SELECT STATEMENT               |                      |            |          |         1|             |     19689|         2|         0|         0|                                |
|  1 |  SUBQUERY                      | QUERY[1]             |            |          |          |             |          |          |          |          |                                |
|  2 |   AGGREGATE                    |                      |            |         1|          |  1150846( 0)|          |          |          |          |                                |
|* 3 |    TABLE ACCESS FULL           | TEST01               | SCOTT      |       446|          |  1150846( 0)|          |          |          |          |                                |
|  4 |  AGGREGATE                     |                      |            |         1|         1|99005259776( 0)|     19688|         2|         0|         0|                                |
|  5 |   VIEW                         |                      |            |     86987|     86987|99005259776( 0)|     16413|     86988|         0|         0|                                |
|  6 |    TABLE ACCESS FULL           | TEST02               | SCOTT      |     86987|     86987|      212( 0)|      6623|     86988|         0|         0|                                |
+----+--------------------------------+----------------------+------------+----------+----------+-------------+----------+----------+----------+----------+--------------------------------+
                                                                
Operation Information (identified by operation id):             
---------------------------------------------------             
                                                                
   3 - Predicate : filter("A"."OBJECT_ID" = "B"."OBJECT_ID")    

Statistics
----------------------------------------------------------------------------------------------------
                    0 physical reads                                                  
                 1315 db block gets                                                   
                    0 consistent gets                                                 
                    0 redo size                                                       
                    0 recursive calls                                                 
                    0 bytes sent via SQL*Net to client                                
                    0 bytes received via SQL*Net from client                          
                    0 SQL*Net roundtrips to/from client                               
                    0 sorts (memory)                                                  
                    0 sorts (disk)                                                    
                    1 rows processed                                                  
                    0 bytes sent via PX                                               
                    0 block received                                                  

32 rows fetched.

Elapsed: 00:00:00.024

结论:崖山支持标量子查询消除(标量子查询部分A-TIME为空,说明没执行),执行计划中应该不显示标量子查询,建议崖山后续修复此问题。还好查看执行计划用的是A-TIME方式,如果用EXPLAIN看执行计划会误认为崖山不支持标量子查询消除

4.自定义函数消除

复制代码
CREATE OR REPLACE FUNCTION f_get_cnt_by_owner(p_owner varchar) RETURN int AS
  v_cnt int;
BEGIN
  IF 1=1 THEN  ---加了这里
  select count(*) into v_cnt from test01 where owner = p_owner;
  END IF;      ---加了这里
  RETURN v_cnt;
END;
/

Oracle

复制代码
SQL> select count(*)
  2    from (select a.*,
  3                 f_get_cnt_by_owner(owner) cnt
  4            from test02 a);

Elapsed: 00:00:00.00

Execution Plan
----------------------------------------------------------
Plan hash value: 322432667

---------------------------------------------------------------------
| Id  | Operation          | Name   | Rows  | Cost (%CPU)| Time     |
---------------------------------------------------------------------
|   0 | SELECT STATEMENT   |        |     1 |   347   (1)| 00:00:01 |
|   1 |  SORT AGGREGATE    |        |     1 |            |          |
|   2 |   TABLE ACCESS FULL| TEST02 | 86987 |   347   (1)| 00:00:01 |
---------------------------------------------------------------------

yashan

复制代码
SQL> select count(*)
  from (select a.*,
               f_get_cnt_by_owner(owner) cnt
          from test02 a);   2    3    4 

Execution Plan                                                   
---------------------------------------------------------------- 
SQL hash value: 2742543714                                      
Optimizer: ADOPT_C                                              
                                                                
+----+--------------------------------+----------------------+------------+----------+----------+-------------+----------+----------+----------+----------+--------------------------------+
| Id | Operation type                 | Name                 | Owner      | E - Rows | A - Rows | Cost(%CPU)  | A - Time | Loops    | Memory   | Disk     | Partition info                 |
+----+--------------------------------+----------------------+------------+----------+----------+-------------+----------+----------+----------+----------+--------------------------------+
|  0 | SELECT STATEMENT               |                      |            |          |         1|             |      3280|         2|         0|         0|                                |
|  1 |  TABLE ACCESS FULL (AGGR PUSHED)| TEST02               | SCOTT      |         1|         1|      212( 0)|      3277|         2|         0|         0|                                |
+----+--------------------------------+----------------------+------------+----------+----------+-------------+----------+----------+----------+----------+--------------------------------+

Statistics
----------------------------------------------------------------------------------------------------
                    0 physical reads                                                  
                 1315 db block gets                                                   
                    0 consistent gets                                                 
                    0 redo size                                                       
                    0 recursive calls                                                 
                    0 bytes sent via SQL*Net to client                                
                    0 bytes received via SQL*Net from client                          
                    0 SQL*Net roundtrips to/from client                               
                    0 sorts (memory)                                                  
                    0 sorts (disk)                                                    
                    1 rows processed                                                  
                    0 bytes sent via PX                                               
                    0 block received                                                  

22 rows fetched.

Elapsed: 00:00:00.008

结论:崖山支持自定义函数消除,不然不可能只跑0.008秒

5.INNER JOIN DISTINCT消除

复制代码
select count(*) from (select distinct * from emp e inner join dept d on e.deptno=d.deptno);

select count(*) from (select unique * from emp e inner join dept d on e.deptno=d.deptno);  

Oracle

复制代码
SQL> select count(*) from (select distinct * from emp e inner join dept d on e.deptno=d.deptno);

Elapsed: 00:00:00.02

Execution Plan
----------------------------------------------------------
Plan hash value: 680252336

-----------------------------------------------------------------------------------
| Id  | Operation        | Name           | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT |                |     1 |     3 |     1   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE  |                |     1 |     3 |            |          |
|*  2 |   INDEX FULL SCAN| IDX_EMP_DEPTNO |    14 |    42 |     1   (0)| 00:00:01 |
-----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter("E"."DEPTNO" IS NOT NULL)

yashan

复制代码
SQL> select count(*) from (select distinct * from emp e inner join dept d on e.deptno=d.deptno);

Execution Plan                                                   
---------------------------------------------------------------- 
SQL hash value: 1267998346                                      
Optimizer: ADOPT_C                                              
                                                                
+----+--------------------------------+----------------------+------------+----------+----------+-------------+----------+----------+----------+----------+--------------------------------+
| Id | Operation type                 | Name                 | Owner      | E - Rows | A - Rows | Cost(%CPU)  | A - Time | Loops    | Memory   | Disk     | Partition info                 |
+----+--------------------------------+----------------------+------------+----------+----------+-------------+----------+----------+----------+----------+--------------------------------+
|  0 | SELECT STATEMENT               |                      |            |          |         1|             |       133|         2|         0|         0|                                |
|  1 |  AGGREGATE                     |                      |            |         1|         1|        1( 0)|       133|         2|         0|         0|                                |
|  2 |   VIEW                         |                      |            |        14|        14|        1( 0)|       131|        15|         0|         0|                                |
|  3 |    SORT DISTINCT               |                      |            |        14|        14|        1( 0)|       123|        15|         0|         0|                                |
|  4 |     NESTED LOOPS INNER         |                      |            |        14|        14|        1( 0)|       101|        15|         0|         0|                                |
|  5 |      TABLE ACCESS FULL         | EMP                  | SCOTT      |        14|        14|        1( 0)|        10|        15|         0|         0|                                |
|  6 |      TABLE ACCESS BY INDEX ROWID| DEPT                 | SCOTT      |         1|          |        1( 0)|          |          |          |          |                                |
|* 7 |       INDEX UNIQUE SCAN        | PK_DEPT              | SCOTT      |         1|         6|        1( 0)|        23|        12|         0|         0|                                |
+----+--------------------------------+----------------------+------------+----------+----------+-------------+----------+----------+----------+----------+--------------------------------+
                                                                
Operation Information (identified by operation id):             
---------------------------------------------------             
                                                                
   3 - Distinct Expression: ("E"."EMPNO"[OPTMZ-3], "D"."LOC"[OPTMZ-2], "D"."DNAME"[OPTMZ-2])
   4 - Execution : NDV ENABLE : 1  NDV Affected Rows : 11  NDV Match Rows : 8  NDV Mem Blocks : 6  NDV Mem Key Size : 27  NDV Mem Value Size : 77  NDV Cost : 0  No NDV Cost : 0  
       Nest Loop Join NDV Expression: ("E"."DEPTNO"[OPTMZ-3][OPTMZ-0])
   7 - Predicate : access("D"."DEPTNO" = "E"."DEPTNO"[OPTMZ-3][OPTMZ-2])

Statistics
----------------------------------------------------------------------------------------------------
                    0 physical reads                                                  
                   19 db block gets                                                   
                    0 consistent gets                                                 
                    0 redo size                                                       
                    0 recursive calls                                                 
                    0 bytes sent via SQL*Net to client                                
                    0 bytes received via SQL*Net from client                          
                    0 SQL*Net roundtrips to/from client                               
                    0 sorts (memory)                                                  
                    0 sorts (disk)                                                    
                    1 rows processed                                                  
                    0 bytes sent via PX                                               
                    0 block received                                                  

36 rows fetched.

Elapsed: 00:00:00.003

SQL> select count(*) from (select unique * from emp e inner join dept d on e.deptno=d.deptno);

[1:30]YAS-04213 expression expected

Elapsed: 00:00:00.000

结论:崖山不支持INNER JOIN DISTINCT消除,另外崖山还不支持SELECT UNIQUE 语法

6.LEFT JOIN 消除

复制代码
select e.empno,e.ename from emp e left join dept d on e.deptno=d.deptno;

Oracle

复制代码
SQL> select e.empno,e.ename from emp e left join dept d on e.deptno=d.deptno;

14 rows selected.

Elapsed: 00:00:00.00

Execution Plan
----------------------------------------------------------
Plan hash value: 3956160932

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |    14 |   140 |     3   (0)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| EMP  |    14 |   140 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------

yashan

复制代码
SQL> select e.empno,e.ename from emp e left join dept d on e.deptno=d.deptno;

Execution Plan                                                   
---------------------------------------------------------------- 
SQL hash value: 2062330261                                      
Optimizer: ADOPT_C                                              
                                                                
+----+--------------------------------+----------------------+------------+----------+----------+-------------+----------+----------+----------+----------+--------------------------------+
| Id | Operation type                 | Name                 | Owner      | E - Rows | A - Rows | Cost(%CPU)  | A - Time | Loops    | Memory   | Disk     | Partition info                 |
+----+--------------------------------+----------------------+------------+----------+----------+-------------+----------+----------+----------+----------+--------------------------------+
|  0 | SELECT STATEMENT               |                      |            |          |        14|             |      2447|        15|         0|         0|                                |
|  1 |  NESTED LOOPS LEFT OUTER       |                      |            |        14|        14|        1( 0)|      2436|        15|         0|         0|                                |
|  2 |   TABLE ACCESS FULL            | EMP                  | SCOTT      |        14|        14|        1( 0)|        46|        15|         0|         0|                                |
|* 3 |   INDEX UNIQUE SCAN            | PK_DEPT              | SCOTT      |         1|         6|        1( 0)|        38|        12|         0|         0|                                |
+----+--------------------------------+----------------------+------------+----------+----------+-------------+----------+----------+----------+----------+--------------------------------+
                                                                
Operation Information (identified by operation id):             
---------------------------------------------------             
                                                                
   1 - Execution : NDV ENABLE : 1  NDV Affected Rows : 11  NDV Match Rows : 8  NDV Mem Blocks : 6  NDV Mem Key Size : 27  NDV Mem Value Size : 27  NDV Cost : 0  No NDV Cost : 0  
       Nest Loop Join NDV Expression: ("E"."DEPTNO"[OPTMZ-3][OPTMZ-0])
   3 - Predicate : access("D"."DEPTNO" = "E"."DEPTNO"[OPTMZ-3][OPTMZ-2])

Statistics
----------------------------------------------------------------------------------------------------
                    0 physical reads                                                  
                   13 db block gets                                                   
                    0 consistent gets                                                 
                    0 redo size                                                       
                    0 recursive calls                                                 
                    0 bytes sent via SQL*Net to client                                
                    0 bytes received via SQL*Net from client                          
                    0 SQL*Net roundtrips to/from client                               
                    0 sorts (memory)                                                  
                    0 sorts (disk)                                                    
                   14 rows processed                                                  
                    0 bytes sent via PX                                               
                    0 block received                                                  

31 rows fetched.

Elapsed: 00:00:00.006

结论:崖山不支持LEFT JOIN消除

后面不用测试了,Oracle都支持,崖山都不支持

7.LEFT JOIN DISTINCT/UNIQUE消除

复制代码
select count(*) from (select distinct * from emp e left join dept d on e.deptno=d.deptno);

8.LEFT JOIN 分析函数消除

复制代码
select count(*)
   from (select e.*, row_number() over(partition by e.deptno order by d.loc) rn
           from emp e
           left join dept d
             on e.deptno = d.deptno);

...等等等,还有很多类似的变种SQL就不一一列举了...

9.LEFT JOIN GROUP BY消除

虽然Oracle支持很多消除技术,但是Oracle目前还不支持我认为很重要的LEFT JOIN GROUP BY消除

比如下面SQL

复制代码
select count(*)
  from test02 a
  left join (select object_id, count(*) from test01 group by object_id) b
    on a.object_id = b.object_id;

PG18

复制代码
postgres=# explain analyze select count(*)
postgres-#   from test02 a
postgres-#   left join (select object_id, count(*) from test01 group by object_id) b
postgres-#     on a.object_id = b.object_id;
                                                      QUERY PLAN                                                      
----------------------------------------------------------------------------------------------------------------------
 Aggregate  (cost=2528.34..2528.35 rows=1 width=8) (actual time=7.282..7.283 rows=1.00 loops=1)
   Buffers: shared hit=1441
   ->  Seq Scan on test02 a  (cost=0.00..2310.87 rows=86987 width=0) (actual time=0.027..4.281 rows=86987.00 loops=1)
         Buffers: shared hit=1441
 Planning Time: 0.066 ms
 Execution Time: 7.303 ms
(6 rows)

Time: 7.618 ms

Oracle

复制代码
SQL> select count(*)
  2    from test02 a
  3    left join (select object_id, count(*) from test01 group by object_id) b
  4      on a.object_id = b.object_id;

Elapsed: 00:00:13.38

Execution Plan
----------------------------------------------------------
Plan hash value: 3748704499

----------------------------------------------------------------------------------------
| Id  | Operation             | Name   | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |        |     1 |    18 |       |   222K  (1)| 00:00:09 |
|   1 |  SORT AGGREGATE       |        |     1 |    18 |       |            |          |
|*  2 |   HASH JOIN OUTER     |        | 86987 |  1529K|       |   222K  (1)| 00:00:09 |
|   3 |    TABLE ACCESS FULL  | TEST02 | 86987 |   424K|       |   347   (1)| 00:00:01 |
|   4 |    VIEW               |        | 88136 |  1118K|       |   221K  (1)| 00:00:09 |
|   5 |     HASH GROUP BY     |        | 88136 |   430K|   511M|   221K  (1)| 00:00:09 |
|   6 |      TABLE ACCESS FULL| TEST01 |    44M|   212M|       |   172K  (1)| 00:00:07 |
----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("A"."OBJECT_ID"="B"."OBJECT_ID"(+))

yashan

复制代码
SQL> select count(*)
  from test02 a
  left join (select object_id, count(*) from test01 group by object_id) b
    on a.object_id = b.object_id;   2    3    4 

Execution Plan                                                   
---------------------------------------------------------------- 
SQL hash value: 2609380292                                      
Optimizer: ADOPT_C                                              
                                                                
+----+--------------------------------+----------------------+------------+----------+----------+-------------+----------+----------+----------+----------+--------------------------------+
| Id | Operation type                 | Name                 | Owner      | E - Rows | A - Rows | Cost(%CPU)  | A - Time | Loops    | Memory   | Disk     | Partition info                 |
+----+--------------------------------+----------------------+------------+----------+----------+-------------+----------+----------+----------+----------+--------------------------------+
|  0 | SELECT STATEMENT               |                      |            |          |         1|             |   8506448|         2|         0|         0|                                |
|  1 |  AGGREGATE                     |                      |            |         1|         1|  1149511( 0)|   8506444|         2|         0|         0|                                |
|* 2 |   HASH JOIN LEFT OUTER         |                      |            |     86987|     86987|  1149510( 0)|   8503307|     86988|         0|         0|                                |
|  3 |    TABLE ACCESS FULL           | TEST02               | SCOTT      |     86987|     86987|      212( 0)|      4907|     86988|         0|         0|                                |
|  4 |    VIEW                        |                      |            |     86987|     86987|  1149278( 0)|   8464424|     86988|         0|         0|                                |
|  5 |     HASH GROUP                 |                      |            |     86987|     86987|  1149278( 0)|   8454903|     86988|         0|         0|                                |
|  6 |      TABLE ACCESS FULL         | TEST01               | SCOTT      |  44537344|  44537344|  1145820( 0)|   2346533|  44537345|         0|         0|                                |
+----+--------------------------------+----------------------+------------+----------+----------+-------------+----------+----------+----------+----------+--------------------------------+
                                                                
Operation Information (identified by operation id):             
---------------------------------------------------             
                                                                
   2 - Execution : Algorithm : 1  PartCount : 1  BuildCount : 86987  BuildDistinct : 87208  BuildSize : 3827428  IsCacheProbe : 0  
       Predicate : access("A"."OBJECT_ID"[OPTMZ-3] = "TEST01"."OBJECT_ID"[OPTMZ-2])
   5 - Execution : PartCount : 1  RowSetCount : 1  TotalChunks : 125  EstimateDistinct : 86987  HllEstimateDistinct : 87208  RealDistinct : 86987  TotalRows : 44537344  MatRows : 86987  SwapCount : 0  Dop : 1  Is2PhaseAggr : 1  CombineTime : 1  
       Group Expression: ("TEST01"."OBJECT_ID"[OPTMZ-1])        

Statistics
----------------------------------------------------------------------------------------------------
                    0 physical reads                                                  
               651026 db block gets                                                   
                    0 consistent gets                                                 
                    0 redo size                                                       
                    0 recursive calls                                                 
                    0 bytes sent via SQL*Net to client                                
                    0 bytes received via SQL*Net from client                          
                    0 SQL*Net roundtrips to/from client                               
                    0 sorts (memory)                                                  
                    0 sorts (disk)                                                    
                    1 rows processed                                                  
                    0 bytes sent via PX                                               
                    0 block received                                                  

35 rows fetched.

Elapsed: 00:00:08.511

结论:PG(其他国产数据库没测)支持LEFT JOIN GROUP BY消除,Oracle,崖山不支持LEFT JOIN GROUP BY消除

Oracle优化器目前还不支持LEFT JOIN GROUP BY消除功能,本人遇到过N次相关案例,最终都是通过人工改写SQL手动消除达到优化目的

举个例子吧(限于SQL原始文本过于复杂,VIEW过于复杂,就不拿出来分享了,见谅):

比如select ...,复杂view一个列 from a left join 复杂view,复杂view里面一堆left join group by left join group by ...

SQL只取复杂view一个列(来自主表),但是复杂view后面有一大堆left join group by,因为Oracle没有left join group by消除功能,所以SQL跑得慢

最终把后面一大堆left join group by干掉后秒杀

结束语:

从内核研发角度来说,上面提到的各种消除技术实现并不难,可能是崖山之前没遇到类似场景,也可能是遇到了类似场景,研发主要精力不在这,相信崖山后面很快能实现上述功能。

PS:还有些消除技术本文没有列举,见谅

相关推荐
知识分享小能手3 小时前
Oracle 19c入门学习教程,从入门到精通,Oracle 表分区与索引分区 —— 语法详解与综合实践(12)
数据库·学习·oracle
dishugj13 小时前
【oracle】19c集群巡检问题
数据库·oracle
知识分享小能手13 小时前
Oracle 19c入门学习教程,从入门到精通,Oracle 其他数据对象 —— 语法详解与综合实践(11)
数据库·学习·oracle
·云扬·18 小时前
深入理解MySQL事务:ACID特性、隔离级别与MVCC原理
数据库·mysql·oracle
傻啦嘿哟18 小时前
用Pydantic验证和解析配置数据:比手写if更可靠
网络·数据库·oracle
小天源18 小时前
麒麟V10互联网安装Oracle11g教程
oracle·oracle 11g·麒麟v10
x***r15119 小时前
oracle11.2.0.4安装步骤详解(附配置与连接教程)
oracle
理智的煎蛋1 天前
达梦数据库全流程操作指南
数据库·oracle
UrSpecial1 天前
IM项目——文件管理子服务
服务器·数据库·oracle