更高效的SQL查询

时间:2011-10-19 17:48:23

标签: sql sql-server

好的,我正在进行数据转换。我的新数据库表中有12个左右的列,我只需要查找旧数据库中每个产品的最新事务。在我的查询中,我需要一个庞大的交易表中的单个值。

要获取最新的交易,我正在使用嵌套的内部联接来查找“最大值”。这些嵌套查询正在扼杀效率,子表格庞大。只抽取100个产品的样本,我的查询大约需要20秒。我有~10,000。有什么建议让我的嵌套查询更有效率?以下是其中一个嵌套内连接的示例。

   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课程,所以我没有学过任何最佳实践,也不知道Big O的成本。哎呀我刚刚在10分钟前找到了执行计划。

更新------------------- 通过删除不必要的列和分组,我能够刮掉几秒钟。所以谢谢。我希望我能让它变得更有效率。我还发现,在可能的情况下,最好在'where'子句中为查询添加限制,而不是直接附加到'JOIN'子句。

X-Zero,我看到它的方式我有两个选择。基本上我正在寻找产品的当前功能。在新数据库中,我将当前功能导入为单个列。在旧数据库中,功能存储在一个巨大的事务表中,该表包含产品上与添加,删除或仅引用功能更改相关的所有事务。产品上的每个功能都在表中设置了自己的事务。如果产品从未拥有该功能,那么根本就没有记录。 (因此使用左连接)我也没有拉动表中的每个要素类型,只有12个。所以我可以:

  1. 按照您的说法并使用CTE制作简化的事务表,该事务表仅包含仅相关功能集的最新活动事务,然后在我的主查询中按产品从此表中提取。

    < / LI>
  2. 正如我现在所做的那样,每个功能在主查询中都有自己独立的子查询/最新事务表。这些表每个只包含一个功能。我尝试使这些子查询完全相同,但是由于表中的许多特征类型我根本没有使用它,因此它们更有效地使它们变得独特。

  3. 我不确定哪条路更好。这听起来像CTE可能是要走的路(只要我将它限制在我想要的12个功能中),但教我自己是另一回事。

2 个答案:

答案 0 :(得分:5)

删除子查询中的DISTINCT关键字; MAX每个GROUPing列只返回一个值,因此DISTINCT是多余的。

编辑:Martin的评论如下是正确的,但它确实增加了子查询中出错的可能性。你需要按所有三列或仅前两列进行分组吗?如果是前者,那么我会收回我的答案;如果是后者,则需要清理样品:)

答案 1 :(得分:1)

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

此外,当优化程序没有做好工作时,请执行