更高效的SQL查询

更高效的SQL查询,sql,sql-server,Sql,Sql Server,好的,我正在做数据转换。我的新数据库表中有12列左右,我只需要找到旧数据库中每个产品的最新事务。在我的查询中,有十二次我需要一个来自大量事务表的单个值 为了获取最新的事务,我使用嵌套的内部联接来查找“max”。这些嵌套查询正在降低效率,而且子表非常庞大。我的查询只需20秒就可以得到100种产品的样本。我有大约10000英镑。有什么建议可以提高嵌套查询的效率吗?下面是其中一个嵌套内部联接的示例 LEFT JOIN coverage_schedule CS_PL ON R.risk_

好的,我正在做数据转换。我的新数据库表中有12列左右,我只需要找到旧数据库中每个产品的最新事务。在我的查询中,有十二次我需要一个来自大量事务表的单个值

为了获取最新的事务,我使用嵌套的内部联接来查找“max”。这些嵌套查询正在降低效率,而且子表非常庞大。我的查询只需20秒就可以得到100种产品的样本。我有大约10000英镑。有什么建议可以提高嵌套查询的效率吗?下面是其中一个嵌套内部联接的示例

   LEFT JOIN coverage_schedule CS_PL
     ON R.risk_pk = CS_PL.risk_fk
        AND CS_PL.coverage_type = 'HOMCVGE'
   LEFT JOIN ( Coverage_tran CT_PL
               JOIN (SELECT DISTINCT MAX(pct.coverage_tran_pk) AS recent,
                                     pct.coverage_schedule_fk,
                                     pcs.coverage_type
                     FROM   Coverage_tran pct
                            LEFT JOIN TRANSACTION pt
                              ON pct.transaction_fk = pt.transaction_pk
                            LEFT JOIN coverage_schedule pcs
                              ON pct.coverage_schedule_fk =
                                 pcs.po_coverage_schedule_pk
                                 AND pcs.coverage_type = 'HOMCVGE'
                     WHERE  pt.transaction_cycle = 'issued'
                            AND pct.cvg_status = 'Active'
                     GROUP  BY pct.coverage_schedule_fk,
                               pcs.coverage_type,
                               pt.transaction_cycle) mCT2
                 ON CT_PL.coverage_schedule_fk = mCT2.coverage_schedule_fk
                    AND CT_PL.coverage_tran_pk = mCT2.recent )
     ON CS_PL.coverage_schedule_pk = CT_PL.coverage_schedule_fk
        AND CT_PL.cvg_status = 'Active'  
我已尝试将嵌套表查询限制为仅具有正确“覆盖率类型”的事务。在此示例中,覆盖率称为“HOMCVGE”,我还将其限制为仅具有“活动”状态的产品。我还尝试从表中删除“coverage”列,因为我不需要它同时作为列和连接的限制/规则。我认为限制样本量会使它更有效,但我看不到明显的效果。我是否只需要通过增加更多限制来缩小表的大小?将限制放在“join”或“where”子句中更好吗

执行计划显示,上面的嵌套查询的成本为11.6911/8%,大约是整个查询中最昂贵的东西。。。但这只是告诉我它会减慢速度,我早就知道了

我可以使用任何提示、线索或工具吗?我承认我没有上过SQL课程,所以我没有学过任何最佳实践,也不知道大O成本。见鬼,我10分钟前才找到执行计划

更新------------------- 通过删除不必要的列和分组,我可以节省几秒钟的时间。谢谢你。我希望我能使它更有效率。我还发现,如果可能,最好在“where”子句中为查询添加一个限制,而不要直接附加到“JOIN”子句

X-Zero,依我看,我有两个选择。基本上,我是在寻找产品的当前功能。在新数据库中,我将当前功能作为单个列导入。在旧数据库中,功能存储在一个巨大的事务表中,其中包括产品上与添加、删除或仅引用功能更改相关的所有事务。产品上的每个功能在表中都有自己的事务集。如果该产品从未有过该功能,那么将不会有任何记录。(因此使用了左连接)我也没有提取表中的每个特征类型,只是12个。因此,我可以:

  • 按照您所说的做,并使用CTE生成一个简化的事务表,该表只包含相关功能集的最新活动事务,然后在我的主查询中按产品从该表中提取

  • 就像我现在所做的那样,每个特性在主查询中都有自己的最近事务的子查询/表。这些表每个仅包含一个要素。我试图使这些子查询完全相同,但由于表中有许多我根本没有使用的功能类型,因此使它们唯一更有效


  • 我不知道哪条路更好。听起来CTE可能是一个不错的选择(只要我把它限制在我想要的12个功能上),但这是另一件我要教自己的事情。

    去掉子查询中的DISTINCT关键字;MAX在每个分组列中只返回一个值,因此DISTINCT是冗余的


    编辑:Martin下面的评论是正确的,但它确实增加了子查询出错的可能性。您需要按所有三列分组还是只按前两列分组?如果是前者,那么我收回我的答案;如果是后者,您需要清理示例:)

    有时,将子查询移动到局部变量中,使它们在使用它们的查询之前成为独立的查询是一种提高性能的方法,强制这些查询只执行一次。当然,这仅适用于某些固定查询。还有一个问题是担心多个查询是否作为单个原子单元执行


    另外,只有当优化器做得不好时才这样做。

    在我看来,如果总成本的8%是11.6911,你可能会有更多的问题。你能发布整个查询,而不仅仅是关注的连接部分吗?您可能可以排除返回的一组列,但至少可以从。。。哪里如果你发布了A)整个查询,B)表定义和C)执行计划,那就好了。请解释一下你想要完成什么。可能不需要三级嵌套。如果您有多个嵌套子查询,都来自同一个基表,您可以使用CTE执行某些汇总(或临时表)吗?根据优化器的智能程度,这可能只会导致一次到基表的过程。好的。我删除了Distinct,并且正在研究如何简化子查询中的列数。我还可以尝试创建一个变量。我从未使用变量创建过大型静态表。如果不是更有效的话,这应该是可能的。至于查询,它有157行长,我花了一天半的时间来写。我不会把整件事都贴出来,然后再解释一遍,以此来折磨每个人。我可能会发布一个简化版本,其中包含各种类型的列的示例。@Stuart刚刚注意到您的编辑引用了我的一条评论。我删除了关于
    DISTINCT
    应用于不同列而不是
    groupby
    的注释,因为我注意到
    中的
    只确保了一个
    pt.transaction\u循环
    组。我认为SQL Server会认识到,
    DISTINCT
    也是多余的。表变量只有在结果集很小的情况下才更有效。如果结果集较大,则使用临时表或CTE