为啥完全相同的查询在 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 选择 V​​MRCTTA1.VMRIACCNT_MC_EXTR_IDX 索引,但 Dev Env 选择 V​​MRCTTA1.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> */

请尝试一下,然后:

检查查询是否确实运行得更快 验证您是否看到在说明中选择了预期的索引

如果这两个问题的答案都是肯定的,那么这意味着索引的统计信息或运行状况肯定有一些不正确的地方,例如生产指数更加分散,这会影响编译期间的成本计算。 假设在 REORGRUNSTATS(我建议 WITH DISTRIBUTION AND DETAILED INDEXES ALL)之后问题仍然存在,请随时从 PROD 上传完整的解释(db2exfmt),以获取有和没有指南的查询。

【讨论】:

以上是关于为啥完全相同的查询在 prod env 中很快,但在 Dev env 中却很慢?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 MySQL DELETE 无法对子查询使用索引?

“未定义窗口中的错误” webpack 上的 webpack 一般错误 --mode=production --env.prod

节点和 Elastic Beanstalk:设置环境 NODE_ENV=prod

如何在environment.prod.ts中将模式保存为ENV变量?

Postgres 不同的查询计划 Prod/QA

使用 repo 机密在 gh 操作中创建 .env 文件