使用合并函数的SQL性能
我有一个SQL查询,在几个表之间有一个连接 当我运行这个查询时,需要1分钟12分钟,但是如果我在accountID周围添加一个合并,我将获得巨大的性能优势,它将在12分钟内运行。请参阅下面完整的未编辑查询使用合并函数的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',
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秒。我看了一下执行计划,但还是不明白为什么联合会产生如此大的影响。谢谢大家。