暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

案例 ▏并行查询导致性能问题

原创 Eygle 2020-03-13
2768

有时候在应用系统中,不正确的使用并行查询也会导致应用问题,以下是一个实际生产中的案例。Statspack 的 Top 5 时间事件输出显示 direct path read 消耗了较高的等待:

Top 5 Timed Events
~~~~~~~~~~~~~~~~~~ % Total
Event Waits Time (s) Ela Time
-------------------------------------------- ------------ ----------- --------
CPU time 5,035 39.49
db file sequential read 444,011 3,582 29.09
direct path read 124,451 1,351 10.60
db file scattered read 389,933 908 7.12
KJC: Wait for msg sends to complete 31,985 600 4.70
 -------------------------------------------------------------

而这个数据库的内存排序率是 100%(In-memory Sort %: 100.00),显然这里的 Direct Path Read 并不是由于排序引发的,注意到另外一个等待事件(KJC: Wait for msg sends to complete)和并行有关,所以初步判断这里的 direct path read 可能和并行有关。

进一步检查 Statspack 报告中的 SQL 部分,发现大量并行查询改写出来的 SQL,这些 SQL通过内部ᨀ示(Hints)固化其执行路径:

 250,458 133 1,883.1 11.9 3.30 29.80 883303536
Module: yy_glxt.exe
SELECT /*+ ORDERED NO_EXPAND USE_NL(A2) INDEX(A2 "SYS_C005617")
*/ A1.C0,A1.C1,A1.C2,A1.C3,A1.C4,A1.C5,A1.C6,A1.C7,A1.C8,A1.C9,A
1.C10,A1.C11,A1.C12,A1.C13,A1.C14,A1.C15,A1.C16,A1.C17,A1.C18,A1
.C19,A1.C20,A1.C21,A1.C22,A1.C23,A1.C24,A1.C25,A1.C26,A1.C27,A1.
C28,A1.C29,A1.C30,A1.C31,A1.C32,A1.C33,A1.C34,A1.C35,A1.C36,A1.C
 201,912 9 22,434.7 9.6 3.82 239.60 1246116920
Module: dmxt.exe
SELECT /*+ Q84417000 NO_EXPAND ROWID(A1) */ A1."ZXBMDM" C0,A1."F
MDM" C1,A1."FMGG" C2,A1."PFJE" C3,A1."JE" C4,A1."LSL" C5,A1."FMM
C" C6 FROM "YYGL"."MZ101_2" PX_GRANULE(0, BLOCK_RANGE, DYNAMIC)
A1 WHERE (TO_CHAR(A1."SFRQ",'yyyy/mm/dd')=:B1 AND A1."JE">0 OR
TO_CHAR(A1."TFRQ",'yyyy/mm/dd')=:B2 AND A1."JE"<0) AND RTRIM(A1.

在很多情况下,并行也许并不是最好的选择,如果表并不大,并行反而会降低其执行速
度。这个用户环境正是如此,询问用户,从未主动启用并行。

通过查询 DBA_TABLES 字典表可以获得 Degree 并行度的记录,并行度大于 1 的数据表
在查询时会启用并行,但是注意事实还会有所不同, Degree 字段的类型及长度是
VARCHAR2(10)。所以注意,当使用类似如下查询时,可能无法获得返回值:

SQL> select table_name from dba_tables where degree='1' or degree='DEFAULT';
no rows selected

我们看一下 Degree 以及 Instances 的记录方式:

 SQL> select degree,length(degree) from dba_tables group by degree;
 DEGREE LENGTH(DEGREE)
 -------------------- --------------
 DEFAULT 10
 1 10
 SQL>select instances,length(instances) from dba_tables group by instances;
 INSTANCES LENGTH(INSTANCES)
 -------------------- -----------------
 DEFAULT 10
 1 10
 0 10

Degree 和 Instances 实际上记录了 10 个字符,左端用空格补齐。在 dba_tables 的创建语句中,可以找到根本原因,以下是这两个字段的定义来源:

 lpad(decode(t.degree, 32767, 'DEFAULT', nvl(t.degree,1)),10),
 lpad(decode(t.instances, 32767, 'DEFAULT', nvl(t.instances,1)),10),

而需要注意的是,如果 Degree 设置为 DEFAULT,则默认数据库会对该表启用并行。最
后找到相关的 SQL,从 AUTOTRACE 可以看到这些 SQL 的执行计划:

SQL> SELECT t1.fmdm, t1.fmmc, t1.sfdldm, t2.sfdlmc, t1.sfxldm, t3.sfxlmc, t1.fmdm,
 2 t1.fmmc, t1.dw, t1.dj, t1.fmshrm, NVL (t1.jeflag, '0'), t1.htbh,
 3 NVL (t1.zhflag, 0), t1.ybfl, t1.ybdm, '3'
 4 FROM sf007 t1, sf001 t2, sf006 t3
 5 WHERE t2.mzflag = '1'
 6 AND t1.sfdldm = t2.sfdldm
 7 AND t1.sfdldm = t3.sfdldm(+)
 8 AND t1.sfxldm = t3.sfxldm(+)
 9 /
1005 rows selected.
Execution Plan
----------------------------------------------------------
 0 SELECT STATEMENT Optimizer=CHOOSE (Cost=8 Card=16 Bytes=2192)
 1 0 HASH JOIN* (Cost=8 Card=16 Bytes=2192):Q91507003
 2 1 TABLE ACCESS* (FULL) OF 'SF001' (Cost=2 Card=4 Bytes=52):Q91507000
 3 1 HASH JOIN* (OUTER) (Cost=6 Card=1634 Bytes=202616):Q91507003
 4 3 TABLE ACCESS* (FULL) OF 'SF007' (Cost=5 Card=1634 Bytes=160132):Q91507001
 5 3 TABLE ACCESS* (FULL) OF 'SF006' (Cost=1 Card=409 Bytes=10634):Q91507002
 1 PARALLEL_TO_SERIAL SELECT /*+ ORDERED NO_EXPAND USE_HASH(A2) SW
 AP_JOIN_INPUTS(A2) */ A1.C0,A2.C1,A1
 2 PARALLEL_FROM_SERIAL
 3 PARALLEL_COMBINED_WITH_PARENT
 4 PARALLEL_FROM_SERIAL
 5 PARALLEL_TO_PARALLEL SELECT /*+ NO_EXPAND ROWID(A1) */ A1."SFDLDM
 " C0,A1."SFXLDM" C1,A1."SFXLMC" C2 F

查看涉及数据表的并行度,注意到其并行度被设置为 DEFAULT:

SQL> select table_name,degree from dba_tables where table_name=’SF006’; 
TABLE_NAME DEGREE
------------------------------ ----------
SF006 DEFAULT

将表的并行度修改为 1 后,问题得以解决:

SQL> alter table sf006 parallel 1; 
Table altered.

这个问题给我们的启示是:并行并不总能够带来性能提升。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论