YashanDB Vs Oracle 10053 event(及Order by Elimination)

oracle 的10046和10053 event是SQL优化时研究优化器的一些手段,前面测试过Oceanbase 的10053 event,本篇尝试YashanDB的。及以一个小例子看看在order by消除等查询转换是否支持。

Oracle 19C

选择一个较常见的场景,有时应用框架在做分布查询前需要记录总页数,而会直接把分页的SQL前直接套上count算总记录数,这里子查询中可能有分页的order by,其实对于count总数,排序是没有必要的。如果消除一些不必要的同时又不影响最终结果,这算是优化器的强大之处。

SQL> explain plan for select count(*) from (select distinct * from test_ec1 t1   order by 1);
Explained.

SQL> @x2

PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 4118444652

---------------------------------------------------------------------------------
| Id  | Operation            | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |          |     1 |       |     3  (34)| 00:00:01 |
|   1 |  SORT AGGREGATE      |          |     1 |       |            |          |
|   2 |   VIEW               |          |    10 |       |     3  (34)| 00:00:01 |
|   3 |    HASH UNIQUE       |          |    10 |   210 |     3  (34)| 00:00:01 |
|   4 |     TABLE ACCESS FULL| TEST_EC1 |    10 |   210 |     2   (0)| 00:00:01 |
---------------------------------------------------------------------------------
11 rows selected.

SQL> alter table test_ec1 add primary key(id);
Table altered.

SQL> explain plan for select count(*) from (select distinct * from test_ec1 t1   order by 1);
Explained.

SQL> @x2
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 2720188007

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

Note: 可见oracle有order by 消除,还有增加了pk后还有distinct消除,及查询merge合并。

看看oracle 10053中的记录

SQL>  ALTER SESSION SET EVENTS = '10053 TRACE NAME CONTEXT FOREVER, LEVEL 2';
Session altered.

SQL> explain plan for select count(*) from (select distinct * from test_ec1 t1   order by id);
Explained.

SQL> @t

TRACEFILE
---------------------------------------------------------------------------------------------------------------  
/u01/app/oracle/diag/rdbms/testdb/testdb1/trace/testdb1_ora_3796316.trc

SQL> ALTER SESSION SET EVENTS = '10053 TRACE NAME CONTEXT off';
Session altered.




==========

Registered qb: SEL$1 0x766a9750 (PARSER)
---------------------
QUERY BLOCK SIGNATURE
---------------------
  signature (): qb_name=SEL$1 nbfros=1 flg=0
    fro(0): flg=5 objn=0 hint_alias="from$_subquery$_001"@"SEL$1"

Registered qb: SEL$2 0xc5c4ab60 (PARSER)
---------------------
QUERY BLOCK SIGNATURE
---------------------
  signature (): qb_name=SEL$2 nbfros=1 flg=0
    fro(0): flg=4 objn=131491 hint_alias="T1"@"SEL$2"

OPTIMIZER INFORMATION

******************************************
----- Current SQL Statement for this session (sql_id=5f9nd9f27z64r) -----
explain plan for select count(*) from (select distinct * from test_ec1 t1   order by id)
*******************************************
Legend
The following abbreviations are used by optimizer trace.
CBQT - cost-based query transformation
JPPD - join predicate push-down
OJPPD - old-style (non-cost-based) JPPD
FPD - filter push-down
PM - predicate move-around
CVM - complex view merging
SPJ - select-project-join
SJC - set join conversion
SU - subquery unnesting
OBYE - order by elimination
OST - old style star transformation
ST - new (cbqt) star transformation
CNT - count(col) to count(*) transformation
JE - Join Elimination
JF - join factorization
CBY - connect by
SLP - select list pruning
DP - distinct placement
VT - vector transformation
AAT - Approximate Aggregate Transformation
ORE - CBQT OR-Expansion
LORE - Legacy OR-Expansion
...

  *************************************
  PARAMETERS WITH DEFAULT VALUES
  ******************************
Compilation Environment Dump
optimizer_mode_hinted               = false
optimizer_features_hinted           = 0.0.0
parallel_execution_enabled          = true
parallel_query_forced_dop           = 0
parallel_dml_forced_dop             = 0
parallel_ddl_forced_degree          = 0
parallel_ddl_forced_instances       = 0
_query_rewrite_fudge                = 90
optimizer_features_enable           = 19.1.0
_optimizer_search_limit             = 5
cpu_count                           = 4
active_instance_count               = 1
parallel_threads_per_cpu            = 1
hash_area_size                      = 131072
bitmap_merge_area_size              = 1048576
sort_area_size                      = 65536
sort_area_retained_size             = 0
_sort_elimination_cost_ratio        = 0
_optimizer_block_size               = 8192
_sort_multiblock_read_count         = 2
...

OBYE:   Considering Order-by Elimination from view SEL$1 (#0)
***************************
Order-by elimination (OBYE)
***************************
OBYE:   Considering Order-by Elimination from view SEL$2 (#0)
***************************
Order-by elimination (OBYE)
***************************
OBYE: Removing order by from query block SEL$2 (#0) (order not used)
Registered qb: SEL$73523A42 0xc5c4ab60 (ORDER BY REMOVED FROM QUERY BLOCK SEL$2; SEL$2)


---------------------
QUERY BLOCK SIGNATURE
---------------------
  signature (): qb_name=SEL$73523A42 nbfros=1 flg=0
    fro(0): flg=0 objn=131491 hint_alias="T1"@"SEL$2"

OBYE:     OBYE performed.
OBYE:     OBYE bypassed: no order by to eliminate.
Eliminated SELECT DISTINCT from query block SEL$73523A42 (#0)

CVM:   Merging SPJ view SEL$73523A42 (#0) into SEL$1 (#0)

Registered qb: SEL$51F12574 0x766a9750 (VIEW MERGE SEL$1; SEL$73523A42; SEL$1)
---------------------
QUERY BLOCK SIGNATURE
---------------------
  signature (): qb_name=SEL$51F12574 nbfros=1 flg=0
    fro(0): flg=0 objn=131491 hint_alias="T1"@"SEL$2"

Final query after transformations:******* UNPARSED QUERY IS *******
SELECT COUNT(*) "COUNT(*)" FROM "SYS"."TEST_EC1" "T1"
kkoqbc: optimizing query block SEL$51F12574 (#1)
...

Note: 优化器参数,一些优化转换,后面是cost及最佳执行计划,只粘贴了部分。

YashanDB 23.5

同样的表结构,注意test_ec1表上有pk主键。

SQL> explain select count(*) from (select distinct * from test_ec1 t1   order by 1);

PLAN_DESCRIPTION
----------------------------------------------------------------
SQL hash value: 3637367764
Optimizer: ADOPT_C

+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+
| Id | Operation type                 | Name                 | Owner      | Rows     | Cost(%CPU)  | Partition info                 |
+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+
|  0 | SELECT STATEMENT               |                      |            |          |             |                                |
|  1 |  AGGREGATE                     |                      |            |         1|       19( 0)|                                |
|  2 |   VIEW                         |                      |            |      2349|       19( 0)|                                |
|  3 |    INDEX FAST FULL SCAN        | IDX_EC1_ID           | SYS        |      2349|       19( 0)|                                |
+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+


Note: yashanDB 同样也消除了Order by ,和distinct 消除,但是没有做 view merge.

看看yashanDB 10053 event

Connected to:
YashanDB Server Enterprise Edition Release 23.5.1.100 x86_64 - Linux

SQL> ALTER SESSION SET TRACE_FILE_IDENTIFIER = 'YashanDB_Trace';

Succeed.

SQL> ALTER SESSION SET EVENTS = '10053 TRACE NAME CONTEXT FOREVER, LEVEL 2';

Succeed.

SQL> explain select count(*) from (select distinct * from test_ec1 t1   order by object_id);

PLAN_DESCRIPTION
----------------------------------------------------------------
SQL hash value: 432293891
Optimizer: ADOPT_C

+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+
| Id | Operation type                 | Name                 | Owner      | Rows     | Cost(%CPU)  | Partition info                 |
+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+
|  0 | SELECT STATEMENT               |                      |            |          |             |                                |
|  1 |  AGGREGATE                     |                      |            |         1|       19( 0)|                                |
|  2 |   VIEW                         |                      |            |      2349|       19( 0)|                                |
|  3 |    INDEX FAST FULL SCAN        | IDX_EC1_ID           | SYS        |      2349|       19( 0)|                                |
+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+

11 rows fetched.

SQL> ALTER SESSION SET EVENTS = '10053 TRACE NAME CONTEXT off';

Succeed.

查看trace 内容

[yashan@yashan-74 ~]$ cd $YASDB_DATA/diag/trace/
[yashan@yashan-74 trace]$ ls -lrt
-rw-r----- 1 yashan yashan    8711 Jan 30 17:23 yashandb_20260130_79_YashanDB_Trace.trc

[yashan@yashan-74 trace]$ vi yashandb_20260130_79_YashanDB_Trace.trc

ashanDB Server Enterprise Edition Release 23.5.1.100 x86_64 037bc48c23
Session ID: 79  (2026-01-30 04:57:25.447)

**************** Trace Start [Event: 10053  Level: 2] ****************
Current SQL statement:
select count(*) from (select distinct * from test_ec1 t1   order by object_id)

*************** CBO Optimize Trace Start *************

Group 0
  Logical : Select [ 1 ]
  Physical 0 :  Select [ 1 ]

Group 1
  Logical : Project [ 2 ]
  Physical 0 :  Project [ 2 ]

Group 2
  Logical : Aggr [ 3 ]
  Physical 0 :  Aggr [ 3 ]

Group 3
  Logical : ViewScan [ 4 ]
  Physical 0 :  ViewScan [ 4 ]

Group 4
  Logical : Select [ 5 ]
  Physical 0 :  Select [ 5 ]

Group 5
  Logical : Project [ 6 ]
  Physical 0 :  Project [ 6 ]

Group 6
  Logical : Scan   Table Name: T1
  Physical 0 :  IndexScan   Index Name: IDX_EC1_ID  Type: INDEX_FULL_SCAN
  Physical 1 :  IndexScan   Index Name: IDX_EC1_ID  Type: INDEX_FAST_FULL_SCAN
  Physical 2 :  TableFullScan   Table Name: T1

  Physical 0: IndexScan
  IndexName:  IDX_EC1_ID  IndexType: INDEX_FULL_SCAN
  Stats:  rows=2349  rowSize=1  keyDistinct=1  columns=1  selectivity=1.000000
  Cost:   self=20.066507  total=20.066507  fetch=0.208940

  Physical 1: IndexScan
  IndexName:  IDX_EC1_ID  IndexType: INDEX_FAST_FULL_SCAN
  Stats:  rows=2349  rowSize=1  keyDistinct=1  columns=1  selectivity=1.000000
  Cost:   self=19.935234  total=19.935234  fetch=0.208916

  Physical 2: TableFullScan
  Stats:  rows=2349  rowSize=1  keyDistinct=1  columns=1  selectivity=1.000000
  Cost:   self=26.645645  total=26.645645  fetch=0.602583

  Group 6 Best :
  Logical : Scan   Table Name: T1
  Best Physical : IndexScan   Index Name: IDX_EC1_ID  Type: INDEX_FAST_FULL_SCAN
  Cost:   self=19.935234  total=19.935234  fetch=0.208916

  Physical 0: Project
  Stats:  rows=2349  rowSize=1  keyDistinct=1  columns=1  selectivity=1.000000
  Cost:   self=0.000000  total=19.935234  fetch=0.208916
...
*************** Trace Bottom Up **********************

Group 6
  Logical : Scan   Table Name: T1
  Physical 0 :  IndexScan   Index Name: IDX_EC1_ID  Type: INDEX_FULL_SCAN
  Physical 1 :  IndexScan   Index Name: IDX_EC1_ID  Type: INDEX_FAST_FULL_SCAN
  Physical 2 :  TableFullScan   Table Name: T1

  Physical 0: IndexScan
  IndexName:  IDX_EC1_ID  IndexType: INDEX_FULL_SCAN
  Stats:  rows=2349  rowSize=1  keyDistinct=1  columns=1  selectivity=1.000000
  Cost:   self=26.645645  total=26.645645  fetch=0.602583

  Physical 1: IndexScan
  IndexName:  IDX_EC1_ID  IndexType: INDEX_FAST_FULL_SCAN
  Stats:  rows=2349  rowSize=1  keyDistinct=1  columns=1  selectivity=1.000000
  Cost:   self=26.645645  total=26.645645  fetch=0.602583

  Physical 2: TableFullScan
  Stats:  rows=2349  rowSize=1  keyDistinct=1  columns=1  selectivity=1.000000
  Cost:   self=26.645645  total=26.645645  fetch=0.602583

  Group 6 Best :
  Logical : Scan   Table Name: T1
  Best Physical : IndexScan   Index Name: IDX_EC1_ID  Type: INDEX_FAST_FULL_SCAN
  Cost:   self=19.935234  total=19.935234  fetch=0.208916
...
***************** CBO Optimize Trace End *************
...

Note: 和oracle比,一个字形容:简陋,支持的消除和查询转换trace中没有输出,当时的CBO parameter在这个版本都没有,文档上看23.4还有。 后面有执行计划cost的对比和执行计划。

小结:

yashanDB 目前支持像oracle中的10053 event,且语法相似, 但是目前的内容输出有较大的提升空间。至少像优化器参数应该输出,方便分析是关因关闭了某参数特性导致的执行计划改变。

Leave a Comment