达梦不支持filter类型的执行路径导致慢SQL

 

达梦不支持filter类型的执行路径导致慢SQL

 

最近有个政府项目的库往政务云上迁移到达梦库,源库的业务量不是很大,库本身也不大。

迁移后抓取达梦的AWR,发现有一条SQL每次执行需要15s多,而在原来的Oracle里边执行0.1s。

查看后发现是达梦不支持filter执行路径导致的。

模拟如下:

创建dgd,p,s共3个表。

create table dgd (hsstr varchar2(20),exstr varchar2(20));
create table p   (id number);
create table s   (id number,hs_str varchar2(40));

 

 

业务SQL如下:

select * from dgd
where exists (select 1
from p, s
where p.id = s.id
and dgd.hsstr || dgd.exstr like s.hs_str || '%');

 

SQL为半连接,关联条件使用了like,因此无论是在Oracle还是达梦都无法使用HASH JOIN算法。

SQL在Oracle和达梦的执行计划如下:

在Oracle和达梦里边,P和S表都使用了HASH JOIN算法。

由于Oracle的FILTER有去重效果,会减少ID为3,4,5的执行次数,

而在达梦里边,NEST LOOP SEMI JOIN2会导致ID为6,7,8的执行次数为DGD的结果集数,没有去重效果。

因此在驱动表关联字段重复数据多的情况下,因为无去重导致达梦实际上就慢很多了。

Oracle:
Plan hash value: 166352517

-----------------------------------------------------------------------------------------------------------------
| Id  | Operation           | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
-----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |      |      1 |        |      0 |00:00:00.01 |       3 |       |       |          |
|*  1 |  FILTER             |      |      1 |        |      0 |00:00:00.01 |       3 |       |       |          |
|   2 |   TABLE ACCESS FULL | DGD  |      1 |      1 |      0 |00:00:00.01 |       3 |       |       |          |
|*  3 |   HASH JOIN         |      |      0 |      1 |      0 |00:00:00.01 |       0 |  1393K|  1393K|          |
|   4 |    TABLE ACCESS FULL| P    |      0 |      1 |      0 |00:00:00.01 |       0 |       |       |          |
|*  5 |    TABLE ACCESS FULL| S    |      0 |      1 |      0 |00:00:00.01 |       0 |       |       |          |
-----------------------------------------------------------------------------------------------------------------

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

   1 - filter( IS NOT NULL)
   3 - access("P"."ID"="S"."ID")
   5 - filter(:B1||:B2 LIKE "S"."HS_STR"||'%')


达梦:
1   #NSET2: [1, 1, 108] 
2     #PRJT2: [1, 1, 108]; exp_num(3), is_atom(FALSE) 
3       #NEST LOOP SEMI JOIN2: [1, 1, 108];  join condition(DGD.HSSTR || DGD.EXSTR LIKE S.HS_STR || '%')[with var]
4         #CSCN2: [1, 1, 108]; INDEX33557305(DGD)
5         #SLCT2: [1, 1, 108]; var4 LIKE S.HS_STR || '%'
6           #HASH2 INNER JOIN: [1, 1, 108];  KEY_NUM(1); KEY(P.ID=S.ID) KEY_NULL_EQU(0)
7             #CSCN2: [1, 1, 30]; INDEX33557306(P)
8             #CSCN2: [1, 1, 78]; INDEX33557308(S)

 

仔细看上边达梦的执行计划,[with var]表示使用了变量改写方式实现连接。

使用hint禁止变量改写之后,执行计划如下:

还是无法避免NEST LOOP。

1   #NSET2: [14, 1, 108] 
2     #PRJT2: [14, 1, 108]; exp_num(3), is_atom(FALSE) 
3       #NEST LOOP SEMI JOIN2: [14, 1, 108];  join condition(DGD.HSSTR || DGD.EXSTR LIKE S.HS_STR || '%')
4         #CSCN2: [1, 1, 108]; INDEX33557305(DGD)
5         #HASH2 INNER JOIN: [1, 1, 108];  KEY_NUM(1); KEY(P.ID=S.ID) KEY_NULL_EQU(0)
6           #CSCN2: [1, 1, 30]; INDEX33557306(P)
7           #CSCN2: [1, 1, 78]; INDEX33557308(S)

关于变量改写,资料太少。官网也搜不到详细的介绍信息。

只有相关hint的时候提到了一下:SQL调优连接方法hint

 

现在发现把半连接改写为内连接在达梦则可以加快速度。

如下:

select dgd.* from dgd,p,s
where p.id = s.id
and dgd.hsstr || dgd.exstr like s.hs_str || '%';

找个时间再研究研究。

 

拓展

当半连接的关联条件为等价连接则可以使用HASH JOIN算法了。

但是需要各自添加hint。

Oracle                                                                                                                      达梦:
select * from dgd                                                                                                           explain select /*+ NO_USE_CVT_VAR OPTIMIZER_MODE(1) */ * from dgd
where exists (select /*+ unnest hash_sj */ 1                                                                                where exists (select  1
from p, s                                                                                                                   from p, s
where p.id = s.id                                                                                                           where p.id = s.id
and dgd.hsstr = s.hs_str );                                                                                                 and dgd.hsstr = s.hs_str );
                                                                                                                            
                                                                                                                            1   #NSET2: [1, 1, 108] 
Plan hash value: 1223244540                                                                                                 2     #PRJT2: [1, 1, 108]; exp_num(3), is_atom(FALSE) 
                                                                                                                            3       #HASH LEFT SEMI JOIN2: [1, 1, 108]; KEY_NUM(1);  KEY(DGD.HSSTR=DMTEMPVIEW_889204724.colname) KEY_NULL_EQU(0)
---------------------------------------------------------------------------------------------------------------------       4         #CSCN2: [1, 1, 108]; INDEX33557305(DGD)
| Id  | Operation            | Name    | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |       5         #PRJT2: [1, 1, 108]; exp_num(1), is_atom(FALSE) 
---------------------------------------------------------------------------------------------------------------------       6           #HASH2 INNER JOIN: [1, 1, 108];  KEY_NUM(1); KEY(P.ID=S.ID) KEY_NULL_EQU(0)
|   0 | SELECT STATEMENT     |         |      1 |        |      0 |00:00:00.01 |       1 |       |       |          |       7             #CSCN2: [1, 1, 30]; INDEX33557306(P)
|*  1 |  HASH JOIN SEMI      |         |      1 |      1 |      0 |00:00:00.01 |       1 |  1160K|  1160K|  451K (0)|       8             #CSCN2: [1, 1, 78]; INDEX33557308(S)
|   2 |   TABLE ACCESS FULL  | DGD     |      1 |      1 |      0 |00:00:00.01 |       1 |       |       |          |       
|   3 |   VIEW               | VW_SQ_1 |      0 |      1 |      0 |00:00:00.01 |       0 |       |       |          |       used time: 1.409(ms). Execute id is 0.
|*  4 |    HASH JOIN         |         |      0 |      1 |      0 |00:00:00.01 |       0 |  1393K|  1393K|          |
|   5 |     TABLE ACCESS FULL| P       |      0 |      1 |      0 |00:00:00.01 |       0 |       |       |          |
|   6 |     TABLE ACCESS FULL| S       |      0 |      1 |      0 |00:00:00.01 |       0 |       |       |          |
---------------------------------------------------------------------------------------------------------------------

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

   1 - access("DGD"."HSSTR"="ITEM_1")
   4 - access("P"."ID"="S"."ID")

 

posted @ 2024-03-08 08:36  PiscesCanon  阅读(44)  评论(0编辑  收藏  举报