为啥完全相同的查询在 prod env 中很快,但在 Dev env 中却很慢?
Posted
技术标签:
【中文标题】为啥完全相同的查询在 prod env 中很快,但在 Dev env 中却很慢?【英文标题】:Why exact same query is fast on prod env but slow in Dev env?为什么完全相同的查询在 prod env 中很快,但在 Dev env 中却很慢? 【发布时间】:2019-10-20 08:08:47 【问题描述】:我有一个查询在 prod env 中需要 10-11 秒,但相同的查询在 Dev env 中返回数据需要很长时间。两种环境中的表和索引都是相同的。 (Prod 和 Dev 都在同一个 VM 上) 两个查询都返回不同的执行计划,显示不同的索引。
Prod Env 选择 VMRCTTA1.VMRIACCNT_MC_EXTR_IDX 索引,但 Dev Env 选择 VMRCTTA1.VMRRACCNT_MC_EXTR_P(从主键自动生成)索引
请帮帮我。
Here is the query:
--INSERT INTO VMRCTTA1."VMRRMC_CD_SUMM"
SELECT
ACCNT_CNTRY_CD,
YTD,
YEAR,
MONTH,
ACCNT_GSSN_CD,
ACCNT_CD,
ACCNT_MC_CD,
COALESCE(REVNU,0)AS REVNU_P,
COALESCE(QTY,0) AS QTY_PC,
ACCNT_MC_DIV AS MC_DIV
FROM
(
SELECT ACCNT_CNTRY_CD,
'Y' AS YTD,
2019 AS YEAR,
2 AS MONTH,
ACCNT_GSSN_CD,
ACCNT_CD,
ACCNT_MC_CD,
SUM(COALESCE(ACCNT_NET_REVNU,0)) AS REVNU,
SUM (COALESCE(ACCNT_QTY,0)) AS QTY,
CASE WHEN ACCNT_MC_DIV = 'P' THEN 'P' WHEN ACCNT_MC_DIV = 'T' THEN 'V' END AS ACCNT_MC_DIV
FROM VMRCTTA1.VMRRACCNT_MC_EXTR ME--, VMRCTTA1.VMRRMC_CD_SPS_MAPPNG CM
WHERE
-- ME.ACCNT_MC_CD = CM.MC_CD
ACCNT_CNTRY_CD = 531
AND ( ACCNT_YEAR = 2019 AND ACCNT_PERIOD <= 2 )
AND ACCNT_MC_DIV IN ('P','T')
GROUP BY
ACCNT_CNTRY_CD,
ACCNT_GSSN_CD,
ACCNT_CD,
ACCNT_MC_CD,
ACCNT_MC_DIV
)AS A
UNION
SELECT
B.ACCNT_CNTRY_CD,
B.YTD,
B.YEAR,
B.MONTH,
B.ACCNT_GSSN_CD,
B.ACCNT_CD,
B.ACCNT_MC_CD,
B.REVNU,
B.QTY,
B.DIV
FROM
(
SELECT
ACCNT_CNTRY_CD,
YTD,
YEAR,
MONTH,
ACCNT_GSSN_CD,
ACCNT_CD,
ACCNT_MC_CD,
MAX(CASE WHEN ACCNT_MC_DIV ='P' THEN COALESCE(REVNU,0) END) AS REVNU_P,
MAX(CASE WHEN ACCNT_MC_DIV ='V' THEN COALESCE(REVNU,0) END) AS REVNU_V,
MAX(CASE WHEN ACCNT_MC_DIV ='P' THEN COALESCE(QTY,0) END) AS QTY_PC,
MAX(CASE WHEN ACCNT_MC_DIV ='V' THEN COALESCE(QTY,0) END) AS QTY_VAN,
'T' AS MC_DIV
FROM
(
SELECT ACCNT_CNTRY_CD,
'Y' AS YTD,
2019 AS YEAR,
2 AS MONTH,
ACCNT_GSSN_CD,
ACCNT_CD,
ACCNT_MC_CD,
SUM(COALESCE(ACCNT_NET_REVNU,0)) AS REVNU,
SUM (COALESCE(ACCNT_QTY,0)) AS QTY,CASE WHEN ACCNT_MC_DIV = 'P' THEN 'P' WHEN ACCNT_MC_DIV = 'T' THEN 'V' END AS ACCNT_MC_DIV
FROM VMRCTTA1.VMRRACCNT_MC_EXTR ME--, VMRCTTA1.VMRRMC_CD_SPS_MAPPNG CM
WHERE
-- ME.ACCNT_MC_CD = CM.MC_CD
ACCNT_CNTRY_CD = 531
AND ( ACCNT_YEAR = 2019 AND ACCNT_PERIOD <= 2 )
AND ACCNT_MC_DIV IN ('P','T')
GROUP BY
ACCNT_CNTRY_CD,
ACCNT_GSSN_CD,
ACCNT_CD,
ACCNT_MC_CD,
ACCNT_MC_DIV
)AS A
GROUP BY
ACCNT_CNTRY_CD,
YTD,
YEAR,
MONTH,
ACCNT_GSSN_CD,
ACCNT_CD,
ACCNT_MC_CD
) AS A,
TABLE
(
VALUES
(A.ACCNT_CNTRY_CD,A.YTD,A.YEAR,A.MONTH,A.ACCNT_GSSN_CD,A.ACCNT_CD,A.ACCNT_MC_CD,COALESCE(A.REVNU_V,0)+COALESCE(A.REVNU_P,0),COALESCE(A.QTY_PC,0)+COALESCE(A.QTY_VAN,0),'T')
)
AS B(ACCNT_CNTRY_CD,YTD,YEAR,MONTH,ACCNT_GSSN_CD,ACCNT_CD,ACCNT_MC_CD,REVNU,QTY,DIV)
【问题讨论】:
请附上从explain all with snapshot for SELECT ...
语句获得并使用db2exfmt 实用程序格式化的两个访问计划。
什么环境?大型机、服务器、台式机?操作系统?
【参考方案1】:
Db2 优化器是基于成本的。除了数据模型之外,还考虑了行数、统计信息(由 runstats 收集)、配置和资源来计算成本。 例如,Db2 配置包含有关 CPUSpeed 的信息,这也很重要——因此这些值在您的开发、测试和生产环境之间可能会有所不同。
这些差异可能导致不同的成本估算可能导致不同的访问计划。
【讨论】:
嗨,Michael,感谢您的回答,我错过了两个 env(Prod 和 Dev)都在同一个 VM 上的问题,那么有什么方法可以提高查询速度吗? 仍然数据(表)大小很重要 - 执行 runstats 并运行解释,然后比较两种环境的输入,这可能会揭示差异【参考方案2】:从 11.1 版开始,您可以使用 embedded optimization guidelines 轻松测试索引差异是否是这里唯一的问题。
在您的具体情况下,您可以将以下指南附加到您的查询中,以强制 Db2 选择 VMRIACCNT_MC_EXTR_IDX
索引:
/* <OPTGUIDELINES><IXSCAN TABLE='VMRCTTA1.VMRRACCNT_MC_EXTR' INDEX='VMRIACCNT_MC_EXTR_IDX'/></OPTGUIDELINES> */
请尝试一下,然后:
检查查询是否确实运行得更快 验证您是否看到在说明中选择了预期的索引如果这两个问题的答案都是肯定的,那么这意味着索引的统计信息或运行状况肯定有一些不正确的地方,例如生产指数更加分散,这会影响编译期间的成本计算。
假设在 REORG
和 RUNSTATS
(我建议 WITH DISTRIBUTION AND DETAILED INDEXES ALL
)之后问题仍然存在,请随时从 PROD 上传完整的解释(db2exfmt
),以获取有和没有指南的查询。
【讨论】:
以上是关于为啥完全相同的查询在 prod env 中很快,但在 Dev env 中却很慢?的主要内容,如果未能解决你的问题,请参考以下文章
“未定义窗口中的错误” webpack 上的 webpack 一般错误 --mode=production --env.prod
节点和 Elastic Beanstalk:设置环境 NODE_ENV=prod