1

我有一个需要 20 分钟才能运行的查询,即使我在 where 子句中的每一列都有一个索引,并且每一列都被加入

SELECT DISTINCT skt.VCDRAWING_REG_NO, skb.NDRAWING_ORG_NO, skb.NDRAWING_ORG_REV_NO, skb.CAPPLY_START_DATE, skb.CAPPLY_END_DATE, skto.*
FROM SPM_ABS_TRANBASE skt
JOIN SPM_ABS_BASE skb
ON skt.NDRAWING_ORG_REV_NO = skb.NDRAWING_ORG_REV_NO
AND skt.NDRAWING_ORG_NO = skb.NDRAWING_ORG_NO
JOIN SPM_ABS_MODEL skm
ON skb.NDRAWING_ORG_REV_NO = skm.NDRAWING_ORG_REV_NO
AND skb.NDRAWING_ORG_NO = skm.NDRAWING_ORG_NO
JOIN SPM_ABS_TRANOPT skto
ON skt.NDRAWING_SYSTEM_NO = skto.NDRAWING_SYSTEM_NO
JOIN ModelImport mi
ON skm.CMODEL = mi.ModelCode
WHERE (skb.CAPPLY_START_DATE <= DATEADD(day, 2, GETDATE()) OR skb.CAPPLY_START_DATE IS NULL)
AND (skb.CAPPLY_END_DATE >= DATEADD(day, -2, GETDATE()) OR skb.CAPPLY_END_DATE IS NULL)

这是我的查询计划

令我困惑的一件事是:如果我添加以下 WHERE 子句,查询会在大约 0.5 秒内返回:

AND mi.ModelCode = '3FBK5'

现在您说,well, duh, of course it gets much faster with that- 问题是,ModelImport 表只包含 351 条记录。这意味着如果我将上面的查询拆分为 351 个查询,每个查询都有自己的 where 子句用于不同的 ModelCode - 那么我可以在大约 175 秒或 2.9 分钟内获得 100% 的查询结果。这要快得多。这告诉我,开放式查询中的某些东西效率极低,而且查询计划也很糟糕。

这是我添加的查询计划AND mi.ModelCode = '3FBK5'

查看我的查询计划后,有什么想法可以加快速度吗?

4

2 回答 2

0

如果没有表架构和大小,很难给出准确的答案,但这里有一些更新可以尝试。

  • 使用 group by 而不是 distinct
  • 不要在选择结果中使用 * (尤其是不同的),而是给出要返回的特定列列表
  • 避免 where 子句中的“或”语句(也许使用 ISNULL 代替)

以下是这些更新后查询可能的样子(尽管您可能想要添加来自 skto 的其他一些列)

SELECT  skt.VCDRAWING_REG_NO, 
        skb.NDRAWING_ORG_NO, 
        skb.NDRAWING_ORG_REV_NO, 
        skb.CAPPLY_START_DATE, 
        skb.CAPPLY_END_DATE, 
        skto.NDRAWING_SYSTEM_NO
FROM    SPM_ABS_TRANBASE skt
        JOIN SPM_ABS_BASE skb ON 
            skt.NDRAWING_ORG_REV_NO = skb.NDRAWING_ORG_REV_NO
            AND skt.NDRAWING_ORG_NO = skb.NDRAWING_ORG_NO
        JOIN SPM_ABS_MODEL skm ON 
            skb.NDRAWING_ORG_REV_NO = skm.NDRAWING_ORG_REV_NO
            AND skb.NDRAWING_ORG_NO = skm.NDRAWING_ORG_NO
        JOIN SPM_ABS_TRANOPT skto ON 
            skt.NDRAWING_SYSTEM_NO = skto.NDRAWING_SYSTEM_NO
        JOIN ModelImport mi ON 
            skm.CMODEL = mi.ModelCode
WHERE   ISNULL(skb.CAPPLY_START_DATE, DATEADD(day, 2, GETDATE())) <= DATEADD(day, 2, GETDATE())
        AND ISNULL(skb.CAPPLY_END_DATE,DATEADD(day, -2, GETDATE())) >= DATEADD(day, -2, GETDATE())
GROUP BY skt.VCDRAWING_REG_NO, 
        skb.NDRAWING_ORG_NO, 
        skb.NDRAWING_ORG_REV_NO, 
        skb.CAPPLY_START_DATE, 
        skb.CAPPLY_END_DATE,
        skto.NDRAWING_SYSTEM_NO
于 2019-08-16T17:55:12.717 回答
0

您是否有可能消除一些连接,因为您没有从这些表中选择任何内容或将任何 where 条件应用于这些表,例如 skm 和 mi?

于 2019-08-16T17:43:44.877 回答