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

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

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:还有些消除技术本文没有列举,见谅

相关推荐
fen_fen17 小时前
Oracle建表语句示例
数据库·oracle
此刻你21 小时前
常用的 SQL 语句
数据库·sql·oracle
海心焱1 天前
从零开始构建 AI 插件生态:深挖 MCP 如何打破 LLM 与本地数据的连接壁垒
jvm·人工智能·oracle
德彪稳坐倒骑驴1 天前
MySQL Oracle面试题
数据库·mysql·oracle
吕司1 天前
MySQL库的操作
数据库·mysql·oracle
dishugj1 天前
【Oracle】 rac的一些问题以及解决方案
数据库·oracle
eWidget1 天前
面向信创环境的Oracle兼容型数据库解决方案
数据库·oracle·kingbase·数据库平替用金仓·金仓数据库
熊文豪1 天前
关系数据库替换用金仓——Oracle兼容性深度解析
数据库·oracle·金仓数据库·电科金仓·kes
eWidget1 天前
面向Oracle生态的国产高兼容数据库解决方案
数据库·oracle·kingbase·数据库平替用金仓·金仓数据库
A懿轩A1 天前
【MySQL 数据库】MySQL 数据库核心概念详解:库、表、字段、主键与关系型模型一文读懂
数据库·mysql·oracle