优化DB2 Query的方法



我使用下面的SQL语句创建了一个DB2视图。有人可以帮助我如何提高这个视图性能,因为它有时运行缓慢。

我注意到的一件事是,它第一次运行缓慢,但随后的运行,它加快了速度。我用可视化解释进行了分析,但是当它运行缓慢时,我没有看到任何索引建议。所以我不知道如何优化这个

--  Generate SQL 
--  Version:                    V7R4M0 190621 
--  Generated on:               02/09/21 03:08:31 
--  Relational Database:        BIGBLUE 
--  Standards Option:           Db2 for i 
CREATE VIEW IESQAFILE.PSCMPORDVW  
AS 
WITH INPROGRESS AS 
( 
SELECT 
DIODR# 
, DIDISP 
, DIUNIT 
, DISTST 
, DIAPRV 
, DIETAD 
, DITRLR AS TRAILER_ID 
, DIDR1 
, DIETAT 
FROM 
IESQAFILE.LOAD 
WHERE 
DIETAD <> 0 
AND DIETAT <> '0000' 
ORDER BY 
1 
) 
, STOPGROUP AS 
( 
SELECT 
SOORD STOPORDER 
, COUNT(*) STOPSREMAIN 
, MIN(SOSTP#) NEXTSTOP 
, MAX(SOAPPR) APPTREQ 
FROM 
PAVT.STOP 
INNER JOIN 
INPROGRESS 
ON 
DIODR# = SOORD 
WHERE 
SOARDT = 0 
GROUP BY 
SOORD 
ORDER BY 
1 
) 
, STOPAPPTS AS 
( 
SELECT 
SOORD APPTORDER 
, SOCUST STOPCUST 
, SOEDA ETADATE 
, SOETA ETATIME 
, SOADT1 EARLYDATE 
, SOATM1 EARLYTIME 
, SOADT2 LATEDATE 
, SOATM2 LATETIME 
, SOCTYC NEXTCITY 
, SOSTP# APPTSTOP 
, SOST NEXTSTATE 
FROM 
IESQAFILE.STOPOFF 
INNER JOIN 
STOPGROUP 
ON 
STOPORDER = SOORD 
AND NEXTSTOP = SOSTP# 
) 
SELECT 
ORDER_NUMBER 
, SHIPPER_ID 
, SHIPPER_NAME 
, SHIPPER_ADDRESS_1 
, SHIPPER_ADDRESS_2 
, SHIPPER_CITY 
, SHIPPER_ST 
, SHIPPER_ZIP 
, SHIPPER_ZIP_EXT 
, LOAD_AT_ID 
, LOAD_AT_NAME 
, LOAD_AT_ADDRESS_1 
, LOAD_AT_ADDRESS_2 
, LOAD_AT_CITY 
, LOAD_AT_ST 
, LOAD_AT_ZIP 
, LOAD_AT_ZIP_EXT 
, LOAD_AT_LATITUDE 
, LOAD_AT_LONGITUDE 
, EARLY_PU_DATE_TIME 
, LATE_PU_DATE_TIME 
, EARLY_DELV_DATE_TIME 
, EST_REVENUE 
, ORDER_DIV 
, CONSIGNEE_ID 
, CONSIGNEE_NAME 
, CONSIGNEE_ADDRESS_1 
, CONSIGNEE_ADDRESS_2 
, CONSIGNEE_CITY 
, CONSIGNEE_ST 
, CONSIGNEE_ZIP 
, CONSIGNEE_ZIP_EXT 
, CONSIGNEE_LATITUDE 
, CONSIGNEE_LONGITUDE 
, TRAILER_TYPE 
, ORDER_MESSAGE 
, ADDITIONAL_STOPS 
, CMDTY_CODE 
, CMDTY_DESCRIPTION 
, ORDER_MILES 
, ORDER_WGT 
, ORIGIN_CITY_CODE 
, ORIGIN_CITY 
, ORIGIN_ST 
, DEST_CITY_CODE 
, DEST_CITY_NAME 
, DEST_ST 
, PICK_UP_AREA 
, PLAN_INFO 
, NUMBER_LDS 
, NUMBER_DISP 
, SHIP_DATE_TIME 
, NEW_PICKUP_AREA 
, EQUIPMENT_NUMBER 
, APPT_REQ 
, APPT_MADE 
, PRE_T_SEQ 
, PRE_T_AREA 
, LOAD_DISPATCHED 
, CUST_SERV_REP 
, NEGOTIATIONS 
, 
( 
CASE 
WHEN UNUNIT IS NOT NULL 
THEN UNUNIT 
ELSE ' ' 
END 
) 
UNIT_DISPATCHED 
, 
( 
CASE 
WHEN UNSUPR IS NOT NULL 
THEN UNSUPR 
ELSE ' ' 
END 
) 
DRIVER_MGR_CODE 
, COALESCE(SUPNAM, ' ') DRIVER_MGR_NAME 
, 
( 
CASE 
WHEN UNFMGR IS NOT NULL 
THEN UNFMGR 
ELSE ' ' 
END 
) 
FLEET_MGR_CODE 
, COALESCE(FLTNAM,' ') FLEET_MGR_NAME 
                                                                                                                                                                                                                                                                                                                                                                                                      , 
                                                                                                                                                                                                                                                                                                                                                                                                                                           ( 
                                                                                                                                                                                                                                                                                                                                                                                                                                           CASE 
                                                                                                                                                                                                                                                                                                                                                                                                                                       WHEN UNTRL1 IS NOT NULL 
                                                                                                                                                                                                                                                                                                                                                                                                                       THEN UNTRL1 
                                                                                                                                                                                                                                                                                                                                                                                                                                   ELSE ' ' 
                                                                                                                                                                                                                                                                                                                                                                                                                                   END 
                                                                                                                                                                                                                                                                                                                                                                                                                                           ) 
                                                                                                                                                                                                                                                                                                                                                                                                                                           TRAILER_ID, 
                                                                                                                                                                                                                                                                                                                                                                                                                                   DIDISP DISPATCH_NUMBER, 
                                                                                                                                                                                                                                                                                                                                                                                                                       (COALESCE(BCMCNEW, ' ')) FED_MC_ID, 
                                                                                                                                                                                                                                                                                                                                                                                                           DIUNIT DISPATCHED_UNIT, 
                                                                                                                                                                                                                                                                                                                                                                                                                       CASE 
                                                                                                                                                                                                                                                                                                                                                                                                                                       WHEN UNETAD <> 0 
                                                                                                                                                                                                                                                                                                                                                                                                                           AND UNETAT = '' 
                                                                                                                                                                                                                                                                                                                                                                                                                               THEN SMIS.CVTDATETIM(CHAR(UNETAD),'0000', ( 
SELECT 
SUBSTR(DATA_AREA_VALUE, 1109, 2) AS TIMEZONE 
FROM 
TABLE(QSYS2.DATA_AREA_INFO('COMPAN', '*LIBL')) 
) 
) 
WHEN UNETAD <> 0 
THEN SMIS.CVTDATETIM(CHAR(UNETAD),UNETAT, ( 
SELECT 
SUBSTR(DATA_AREA_VALUE, 1109, 2) AS TIMEZONE 
FROM 
TABLE(QSYS2.DATA_AREA_INFO('COMPAN', '*LIBL')) 
) 
) 
WHEN UNETAD = 0 
THEN '0000-00-00T00:00:00-00:00' 
END AS ETA_DATE_TIME, 
NEXTSTOP , CASE 
WHEN SOARDT <> 0 
AND SOARTM = '' 
THEN SMIS.CVTDATETIM(CHAR(SOARDT),'0000', ( 
SELECT 
SUBSTR(DATA_AREA_VALUE, 1109, 2) AS TIMEZONE 
FROM 
TABLE(QSYS2.DATA_AREA_INFO('COMPAN', '*LIBL')) 
) 
) 
WHEN SOARDT <> 0 
THEN SMIS.CVTDATETIM(CHAR(SOARDT),SOARTM, ( 
SELECT 
SUBSTR(DATA_AREA_VALUE, 1109, 2) AS TIMEZONE 
FROM 
TABLE(QSYS2.DATA_AREA_INFO('COMPAN', '*LIBL')) 
) 
) 
WHEN SOARDT = 0 
THEN '0000-00-00T00:00:00-00:00' 
END AS STOP_ARRIVAL_DATE_TIME 
, CASE 
WHEN SOLUDT <> 0 
AND SOLUTM = '' 
THEN SMIS.CVTDATETIM(CHAR(SOLUDT),'0000', ( 
SELECT 
SUBSTR(DATA_AREA_VALUE, 1109, 2) AS TIMEZONE 
FROM 
TABLE(QSYS2.DATA_AREA_INFO('COMPAN', '*LIBL')) 
) 
) 
WHEN SOLUDT <> 0 
THEN SMIS.CVTDATETIM(CHAR(SOLUDT),SOLUTM, ( 
SELECT 
SUBSTR(DATA_AREA_VALUE, 1109, 2) AS TIMEZONE 
FROM 
TABLE(QSYS2.DATA_AREA_INFO('COMPAN', '*LIBL')) 
) 
) 
WHEN SOLUDT = 0 
THEN '0000-00-00T00:00:00-00:00' 
END AS STOP_DEPART_DATE_TIME 
, ORBAMT ORDER_INV_AMT 
, ORARST AR_STATUS_FLAG 
, DISTST SETTLEMENT_FLAG 
, DIAPRV APPROVED_FOR_PAY 
, BCCARR CARRIER_CODE 
, BCNAME CARRIER_NAME 
, BCADDR CARRIER_ADDRESS_1 
, BCADR2 CARRIER_ADDRESS_2 
, BCCITY CARRIER_CITY 
, BCST CARRIER_ST 
, BCZIP CARRIER_ZIP 
FROM 
INPROGRESS 
INNER JOIN 
IESQAFILE.PSMAINORVW A 
ON 
DIODR# = ORDER_NUMBER 
AND DIDISP = NUMBER_DISP 
AND 
( 
SUBSTR(ORDER_NUMBER, 1, 2) <> 'DH' 
AND SUBSTR(ORDER_NUMBER, 1, 1) <> 'M' 
) 
LEFT OUTER JOIN 
IESQAFILE.STOPOFF 
ON 
DIODR# = SOORD 
AND SOSTP# = 90 
LEFT OUTER JOIN 
IESQAFILE.LMCARR 
ON 
DIUNIT = BCCARR 
LEFT OUTER JOIN 
IESQAFILE.MMILES 
ON 
MMORD# = DIODR# 
AND MMRECTYPE = 'D' 
AND MMDSP# = DIDISP 
EXCEPTION JOIN 
IESQAFILE.ORDBILL B 
ON 
B.ORODR# = DIODR# 
AND B.ORSEQ = ' ' 
AND ORARST = '1' 
LEFT OUTER JOIN 
STOPGROUP 
ON 
STOPORDER = DIODR# 
LEFT OUTER JOIN 
STOPAPPTS 
ON 
APPTORDER = STOPORDER 
AND APPTSTOP = NEXTSTOP 
LEFT OUTER JOIN 
IESQAFILE.UNITS 
ON 
UNUNIT = DIUNIT 
AND UNORD# = ORDER_NUMBER 
LEFT OUTER JOIN 
IESQAFILE.SUPMAST 
ON 
SUPCDE = UNSUPR 
LEFT OUTER JOIN 
IESQAFILE.FLTMAST 
ON 
UNFMGR = FLTCDE 
WHERE 
DIETAD <> 0 
AND DIETAT <> '0000'   
RCDFMT PSCMPORDVW ; 

没有看到可视化解释(VE)数据(在这里不是很容易共享的东西)给你一个"魔术棒";答案不太可能。

我很惊讶你没有看到任何索引建议。但即便如此,你也应该能够比较"快速"one_answers"快速"之间的VE数据。和";slow"运行查看差异在哪里。确保你有"视图"- "高亮" "昂贵的图标"- "…打开。还要检查"选项"——>"属性详细信息"one_answers"Options"—;图Detail"…

使用最新版本(1.1.8.6)的访问客户端解决方案(ACS)总是一个好主意,其中包括运行SQL脚本&组件。

一些事情跳出来,包含聚合(计数,最小,最大)的编码向量索引(EVI)可能会在这里有所帮助…

select soord stoporder
,count(*) stopsremain
,min(sostp#) nextstop
,max(soappr) apptreq
from pavt.stop

和索引(或两个)与派生列substr(order_number,....)可能在这里有帮助:

from inprogress
inner join iesqafile.psmainorvw a
on diodr# = order_number
and didisp = number_disp
and (substr(order_number, 1, 2) <> 'DH'
and substr(order_number, 1, 1) <> 'M')
再说一遍,VE是你的朋友,你必须深入了解发生了什么,时间都花在哪里了。

将语句的各个部分分解,并尽可能地优化各个部分。希望当你把它重新组合在一起时,收益仍然存在。

需要记住的一点是,视图与性能无关。它既不会帮助也不会损害性能。

您没有给出如何访问视图的示例,但是您考虑过使用用户定义表函数(UDTF)吗?当查询引擎尝试下推选择标准时,UDTF的参数使您可以轻松地显式包含选择标准。您甚至可能受益于将语句封装在UDTF中,并在UDTF上构建视图。您可以看到message_queue_info视图的示例(通过生成SQL源)&IBM提供的QSYS2中的UDTF。

相关内容

最新更新