SQL Server 2008 - 性能慢查询

Posted

技术标签:

【中文标题】SQL Server 2008 - 性能慢查询【英文标题】:SQL Server 2008 - Slow Performance Query 【发布时间】:2012-06-08 12:46:11 【问题描述】:

我正在运行以下查询:

返回大约 68000 条记录需要 5 分钟。但如果我从查询中删除 LKP_PrivateSource(即最后一个左连接),则需要 1 秒才能返回 68000 条记录。 BTY,LKP_PrivateSource 表中没有记录。知道导致问题的原因吗?

Select
Case IsNull(LNK.StockID,0)
    When 0 Then AE.StockID
    Else LNK.StockID
End StockID,
IsNull(AE.LinkID,0) LinkID,IsNull(LNK.CapitalID,0) CapitalID,DE.SourceName
,AE.SourceDate 'Date'
,IsNull(AE.Formula,'') Formula
From AE_RevenuData AE
Left Join Linking LNK With(NoLock) ON LNK.LinkID=AE.LinkID
Inner Join DE_DataEntities DE ON DE.EntityID=AE.EntityID
Inner Join DataEntityIDs TE ON TE.EntityID=DE.EntityID
Inner Join STG_LockedEntityData STG ON STG.StockID=IsNull(LNK.StockID,AE.StockID) AND STG.CapitalID=IsNull(LNK.CapitalID,0) 
Left Join LKP_PrivateSource PS ON IsNull(PS.PSourceId,0)=IsNull(AE.PSourceID,0)
Where AE.ProjectID IN (13)
AND AE.LinkID IS NOT NULL

请看下面的计划:

  |--Compute Scalar(DEFINE:([Expr1017]=CASE WHEN [Expr1026]=(0) THEN [MYDBNAME].[dbo].[AE_RevenueData].[StockID] as [AE].[StockID] ELSE [MYDBNAME].[dbo].[INV_InvestorFundLinking].[StockID] as [LNK].[StockID] END))
   |--Nested Loops(Left Outer Join, OUTER REFERENCES:([Expr1027]))
        |--Filter(WHERE:([MYDBNAME].[dbo].[STG_LockedEntityData].[StockID] as [STG].[StockID]=isnull([MYDBNAME].[dbo].[INV_InvestorFundLinking].[StockID] as [LNK].[StockID],[MYDBNAME].[dbo].[AE_RevenueData].[StockID] as [AE].[StockID]) AND [MYDBNAME].[dbo].[STG_LockedEntityData].[CapitalID] as [STG].[CapitalID]=[Expr1019]))
        |    |--Compute Scalar(DEFINE:([Expr1019]=isnull([MYDBNAME].[dbo].[INV_InvestorFundLinking].[CapitalID] as [LNK].[CapitalID],(0)), [Expr1026]=isnull([MYDBNAME].[dbo].[INV_InvestorFundLinking].[StockID] as [LNK].[StockID],(0))))
        |         |--Nested Loops(Left Outer Join, OUTER REFERENCES:([AE].[LinkID]))
        |              |--Nested Loops(Inner Join, WHERE:([MYDBNAME].[dbo].[AE_RevenueData].[LinkID] as [AE].[LinkID]=[MYDBNAME].[dbo].[STG_LockedEntityData].[LinkID] as [STG].[LinkID]))
        |              |    |--Sort(ORDER BY:([Expr1027] ASC))
        |              |    |    |--Hash Match(Inner Join, HASH:([TE].[EntityID])=([AE].[EntityID]))
        |              |    |         |--Nested Loops(Inner Join, OUTER REFERENCES:([Uniq1008], [DE].[ListingID]))
        |              |    |         |    |--Nested Loops(Inner Join, OUTER REFERENCES:([TE].[EntityID]))
        |              |    |         |    |    |--Table Scan(OBJECT:([MYDBNAME].[dbo].[DataEntityIDs] AS [TE]))
        |              |    |         |    |    |--Index Seek(OBJECT:([MYDBNAME].[dbo].[DE_DataEntities].[PK_DE_DataSources] AS [DE]), SEEK:([DE].[EntityID]=[MYDBNAME].[dbo].[DataEntityIDs].[EntityID] as [TE].[EntityID]) ORDERED FORWARD)
        |              |    |         |    |--Clustered Index Seek(OBJECT:([MYDBNAME].[dbo].[DE_DataEntities].[IX_DE_DataSources] AS [DE]), SEEK:([DE].[ListingID]=[MYDBNAME].[dbo].[DE_DataEntities].[ListingID] as [DE].[ListingID] AND [Uniq1008]=[Uniq1008]) LOOKUP ORDERED FORWARD)
        |              |    |         |--Compute Scalar(DEFINE:([Expr1018]=[MYDBNAME].[dbo].[AE_RevenueData].[LinkID] as [AE].[LinkID], [Expr1020]=isnull([MYDBNAME].[dbo].[AE_RevenueData].[Formula] as [AE].[Formula],''), [Expr1021]=CONVERT(bit,[MYDBNAME].[dbo].[AE_RevenueData].[IsSumOfFunds] as [AE].[IsSumOfFunds],0), [Expr1022]=isnull([MYDBNAME].[dbo].[AE_RevenueData].[ClientSpecificSource] as [AE].[ClientSpecificSource],N''), [Expr1023]=isnull([MYDBNAME].[dbo].[AE_RevenueData].[GenericSource] as [AE].[GenericSource],N''), [Expr1027]=isnull([MYDBNAME].[dbo].[AE_RevenueData].[PSourceID] as [AE].[PSourceID],(0))))
        |              |    |              |--Clustered Index Seek(OBJECT:([MYDBNAME].[dbo].[AE_RevenueData].[IX_AE_RevenueData] AS [AE]), SEEK:([AE].[ProjectID]=(13)),  WHERE:([MYDBNAME].[dbo].[AE_RevenueData].[LinkID] as [AE].[LinkID] IS NOT NULL) ORDERED FORWARD)
        |              |    |--Table Scan(OBJECT:([MYDBNAME].[dbo].[STG_LockedEntityData] AS [STG]))
        |              |--Index Seek(OBJECT:([MYDBNAME].[dbo].[INV_InvestorFundLinking].[PK_Linking_1] AS [LNK]), SEEK:([LNK].[LinkID]=[MYDBNAME].[dbo].[AE_RevenueData].[LinkID] as [AE].[LinkID]) ORDERED FORWARD)
        |--Clustered Index Seek(OBJECT:([MYDBNAME].[dbo].[LKP_PrivateSource].[PK_LKP_FactsetSource] AS [PS]), SEEK:([PS].[PSourceID]=[Expr1027]) ORDERED FORWARD)

【问题讨论】:

展示你的计划。 SSMS、查询、显示预计执行计划。 使用EXPLAIN 并尝试检查失败的地方。 @aF.:SQL Server 中没有 EXPLAIN 要生成计划,请运行SET SHOWPLAN_TEXT ON GO SELECT CASE ... @Quassnoi 是的,你明白我的意思:P 【参考方案1】:

我认为这是因为您在左连接的比较两边都使用了函数。

如何修复它实际上取决于业务逻辑,但我会考虑在该表上执行两个或多个左连接。

一个具有直接的值到值比较,而其他的只处理空值逻辑。

您需要将它们添加到您的合并中,按它们如何满足要求进行排序。

【讨论】:

不是因为IsNull,我试过删除它。但输出保持不变。

以上是关于SQL Server 2008 - 性能慢查询的主要内容,如果未能解决你的问题,请参考以下文章

sql server执行几十万条sql很慢,怎么办?

数据库监控&性能优化

转载:SQL Server 2008-建立分区表(Table Partition) 转载

MySQL 优化

SQL Server 2008 Query 生产速度慢,但开发速度快

SQL Server 2008 R2:优化查询性能