使用合并函数的SQL性能

使用合并函数的SQL性能,sql,sql-server,Sql,Sql Server,我有一个SQL查询,在几个表之间有一个连接 当我运行这个查询时,需要1分钟12分钟,但是如果我在accountID周围添加一个合并,我将获得巨大的性能优势,它将在12分钟内运行。请参阅下面完整的未编辑查询 SELECT dbo.CaptionMapItem.CaptionMapItemID, dbo.CaptionMapItem.NodeText, CaptionMapItem_1.NodeText AS 'Level1_Caption',

我有一个SQL查询,在几个表之间有一个连接

当我运行这个查询时,需要1分钟12分钟,但是如果我在accountID周围添加一个合并,我将获得巨大的性能优势,它将在12分钟内运行。请参阅下面完整的未编辑查询

    SELECT dbo.CaptionMapItem.CaptionMapItemID, 
       dbo.CaptionMapItem.NodeText, 
       CaptionMapItem_1.NodeText AS 'Level1_Caption', 
       CaptionMapItem_2.NodeText AS 'Level2_Caption', 
       dbo.Account.Account, 
       SUM(CASE Tx.CurrencyID WHEN 4 THEN dbo.Tx.AmountGross END) AS 'USD_Total',
       SUM(CASE Tx.CurrencyID WHEN 5 THEN dbo.Tx.AmountGross END) AS 'GBP_Total',
       SUM(CASE Tx.CurrencyID WHEN 6 THEN dbo.Tx.AmountGross END) AS 'CAD_Total',
       SUM(CASE Tx.CurrencyID WHEN 7 THEN dbo.Tx.AmountGross END) AS 'EUR_Total' 
  FROM dbo.CaptionMapItem 
       INNER JOIN dbo.CaptionMapItem AS CaptionMapItem_1 
          ON dbo.CaptionMapItem.CaptionMapItemID = CaptionMapItem_1.ParentID 
       INNER JOIN dbo.CaptionMapItem AS CaptionMapItem_2 
          ON CaptionMapItem_1.CaptionMapItemID = CaptionMapItem_2.ParentID 
       LEFT OUTER JOIN dbo.CaptionMapItemAccount 
         ON CaptionMapItem_2.CaptionMapItemID = dbo.CaptionMapItemAccount.CaptionMapItemID 
       LEFT OUTER JOIN dbo.Account 
         ON dbo.CaptionMapItemAccount.AccountID = dbo.Account.AccountID 
       LEFT OUTER JOIN dbo.Tx 
         ON dbo.Account.AccountID = dbo.Tx.CreditAccountID 
 GROUP BY dbo.CaptionMapItem.CaptionMapItemID, 
          dbo.CaptionMapItem.NodeText, 
          CaptionMapItem_1.NodeText, 
          CaptionMapItem_2.NodeText, 
          dbo.Account.Account 
HAVING dbo.CaptionMapItem.NodeText LIKE '%CashFLow%'

在运行查询分析器时,它在accountID联接周围添加了一个合并。但是,当合并在任何联接上时,它也会更快地减少。

通过将
dbo.Account.AccountID
包装到
coalesce
中,可以使条件无法组织

SQL Server
无法再在
dbo.Account.AccountID
上使用带索引搜索的嵌套循环,它将改为使用
MERGE JOIN
HASH JOIN
进行索引扫描

更新:

假设您的
CaptionMapItem
CaptionMapItemAccount
保留了密钥,请尝试以下查询:

SELECT  *
FROM    (
        SELECT  dbo.CaptionMapItem.CaptionMapItemID, 
                dbo.CaptionMapItem.NodeText, 
                CaptionMapItem_1.NodeText AS 'Level1_Caption', 
                CaptionMapItem_2.NodeText AS 'Level2_Caption',
                AccountID
        FROM    dbo.CaptionMapItem 
        JOIN    dbo.CaptionMapItem AS CaptionMapItem_1 
        ON      dbo.CaptionMapItem.CaptionMapItemID = CaptionMapItem_1.ParentID 
        JOIN    dbo.CaptionMapItem AS CaptionMapItem_2 
        ON      CaptionMapItem_1.CaptionMapItemID = CaptionMapItem_2.ParentID 
        LEFT JOIN
                dbo.CaptionMapItemAccount
        ON      CaptionMapItem_2.CaptionMapItemID = dbo.CaptionMapItemAccount.CaptionMapItemID 
        LEFT JOIN
                dbo.Account 
        ON      dbo.CaptionMapItemAccount.AccountID = dbo.Account.AccountID 
        WHERE   dbo.CaptionMapItem.NodeText LIKE '%CashFLow%'
        ) qA
OUTER APPLY
        (
        SELECT  SUM(CASE Tx.CurrencyID WHEN 4 THEN dbo.Tx.AmountGross END) AS 'USD_Total',
                SUM(CASE Tx.CurrencyID WHEN 5 THEN dbo.Tx.AmountGross END) AS 'GBP_Total',
                SUM(CASE Tx.CurrencyID WHEN 6 THEN dbo.Tx.AmountGross END) AS 'CAD_Total',
                SUM(CASE Tx.CurrencyID WHEN 7 THEN dbo.Tx.AmountGross END) AS 'EUR_Total'
        FROM    dbo.Tx 
        WHERE   dbo.Tx.CreditAccountID = qA.AccountID
        ) qTX

谢谢,我们能用任何功能来代替聚结吗?我尝试用isNull()包装连接,但又花了1米12秒。它只适用于合并而不适用于其他函数吗?
@Stephen
:您的整个查询不必要地过于复杂。您真的需要这些提示吗,
左加入
s和
分组方式
?抱歉,我在粘贴查询时删除了其他列的汇总。这就是为什么我有左连接和组。这种合并是通过TOADs new SQL Optimizer运行查询的结果。再次感谢您能否在通过
TOAD
优化之前发布整个查询?谢谢。我试过了,但出现了语法错误。我想这是复印件上的东西,但非常感谢。哎哟!与“%CashFLow%”类似,这将影响查询。把它从HAVING移动到WHERE,这可能会有帮助,因为在你尝试分组之前,你会删除你不想要的行。干杯,我已经尝试过了,它在12秒左右出现了,只要我仍然在join上使用coalesce函数——有点困惑——你说查询需要“1分钟12”但是添加一个coasece会给您带来性能优势,并且它只需12分钟就可以运行?这应该是秒吗?除此之外,您是否尝试过查看查询的执行计划?在SQL-92中,COALESCE是一个表达式,但BOL使用了术语“function”,因此我不会对您进行标记;)对不起,应该是12秒。我看了一下执行计划,但还是不明白为什么联合会产生如此大的影响。谢谢大家。