为提高效率,提问时请提供以下信息,问题描述清晰可优先响应。
【DM版本】:8.1,安全版,DB Version: 0x7000c
【操作系统】:麒麟 V10
【CPU】:16核 ARMv8 CPU
【问题描述】*:
刚从oracle搬迁到云达梦,发现类似如下半连接sql只能走NEST LOOP SEMI JOIN2,在oracle里边0.1s,在达梦要15s多。
类似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 || '%');
无论是达梦还是Oracle,HASH算法都不支持连接条件为like。
所以在oracle里边走了filter,但也比达梦的nl要快的多。
怎么让达梦不使用NEST LOOP SEMI JOIN2。
另外补充说明:关联条件均无索引存在,也就是涉及的3个表都是全表扫描。
Oracle里边的表统计信息都是没问题的并没有使用了动态采样技术。
简单创建表进行测试,脚本如下:
create table dgd (hsstr varchar2(20),exstr varchar2(20));
create table p (id number);
create table s (id number,hs_str varchar2(40));
在Oracle里边执行计划:
-----------------------------------------------------------------------------------------------------------------
| 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"||'%')
在达梦里边执行计划:
SQL> alter session set 'MONITOR_SQL_EXEC'=1;
DMSQL executed successfully
used time: 1.810(ms). Execute id is 11707.
SQL> select * from dgd
2 where exists (select 1
3 from p, s
4 where p.id = s.id
5 and dgd.hsstr || dgd.exstr like s.hs_str || '%');
no rows
used time: 0.641(ms). Execute id is 11708.
SQL> set linesize 5000
SQL> et(11708);
LINEID OP TIME(US) PERCENT RANK SEQ N_ENTER MEM_USED(KB) DISK_USED(KB) HASH_USED_CELLS HASH_CONFLICT DHASH3_USED_CELLS DHASH3_CONFLICT HASH_SAME_VALUE
------- ----- ---------- ------- ------- ----- ----------- ------------- -------------- ----------------- --------------- ----------------- --------------- --------------------
1 PRJT2 2 1.18% 5 2 2 0 0 0 0 NULL NULL 0
2 DLCK 7 4.12% 4 0 2 0 0 0 0 NULL NULL 0
3 NLS2 10 5.88% 3 3 2 0 0 0 0 NULL NULL 0
4 NSET2 59 34.71% 2 1 2 0 0 0 0 NULL NULL 0
5 CSCN2 92 54.12% 1 4 1 0 0 0 0 NULL NULL 0
used time: 35.821(ms). Execute id is 11721.
SQL> explain select * from dgd
2 where exists (select 1
3 from p, s
4 where p.id = s.id
5 and dgd.hsstr || dgd.exstr 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)
这个有点意思~估计是和ORACLE的执行计划不一样,需要更详细的资料才能进一步分析。
ORACLE那端可能存在组合列的统计信息或者动态收集了统计信息,所以走上了“捷径”;DM这边缺失统计信息或者相关参数没开启,应该也有办法,需要提供下目前的执行计划详情,建议通过disql工具连接数据库执行:
sf_set_session_para_value('MONITOR_SQL_EXEC',1);
set autotrace trace
-- 执行这个15s语句
set autotrace off
et(?); -- 输入以上语句执行完成输出的“执行号”代码
/+NO_USE_NL(A,B)/强制不走嵌套
可以试一下exists改写为inner join+distinct子查询,并且通过stat hint调整DGD表为被驱动表
select /*+ stat(p,10) stat(s,10) stat(d,1M) */ d.* from dgd d
inner join
(select distinct s.hs_str from p,s where p.id=s.id) ps
on d.hsstr || d.exstr like ps.hs_str || '%'
1 #NSET2: [20809, 500000, 204]
2 #PRJT2: [20809, 500000, 204]; exp_num(2), is_atom(FALSE)
3 #SLCT2: [20809, 500000, 204]; D.HSSTR || D.EXSTR LIKE PS.HS_STR || '%'
4 #NEST LOOP INNER JOIN2: [20809, 500000, 204];
5 #PRJT2: [3, 10, 108]; exp_num(1), is_atom(FALSE)
6 #DISTINCT: [3, 10, 108]
7 #HASH LEFT SEMI JOIN2: [2, 23, 108]; KEY_NUM(1); KEY(S.ID=P.ID) KEY_NULL_EQU(0)
8 #CSCN2: [1, 10, 78]; INDEX33571342(S)
9 #CSCN2: [1, 8673, 30]; INDEX33571341(P)
10 #CSCN2: [124, 1000000, 96]; INDEX33571340(DGD as D)
关于HINT的使用方法,详情见DM8系统管理员手册.pdf
文档在数据库安装路径dmdbms\doc下可找到。
指定索引见23.6.2 章节 索引提示。