繁体   English   中英

试图找到长期运行的SQL代码的解决方案,而我认为NESTED SQL语句是元凶

[英]Trying to find a solution to long running SQL code where I think NESTED SQL statement is the culprit

我有一个SQL语句,其中有一个奇怪的第二个嵌套SQL语句,我认为这会导致该查询运行6分钟以上,任何建议/帮助都将不胜感激。 我尝试为嵌套的SQL语句中的值创建TEMP表,只是执行简单的连接,但是SQL代码中没有要进行的连接,因此这就是为什么它们在ON语句中使用1 = 1进行连接的原因。 这是SQL代码:

Declare @TransactionEndDate datetime;
Select @TransactionEndDate = lastmonth_end from dbo.DTE_udfCommonDates(GETDATE());

Select ''''+TreatyName as Treaty,
cast(EndOfMonth as Date) as asOfDate,
Count(Distinct ClaimSysID) as ClaimCount,
Count(Distinct FeatureSysID) as FeatureCount,
Sum(OpenReserve) as OpenReserve
From (
    Select  
       TreatyName,
       EndOfMonth,
       dbo.CMS_Claims.ClaimSysID,
       FeatureSysID,
       sum(IW_glGeneralLedger.TransactionAmount)*-1 as OpenReserve
    From  dbo.CMS_Claims 
        Inner Join dbo.CMS_Claimants 
        On dbo.CMS_Claims.ClaimSysID = dbo.CMS_Claimants.ClaimSysID
        Inner Join dbo.CMS_Features 
        On dbo.CMS_Features.ClaimantSysID = dbo.CMS_Claimants.ClaimantSysID 
        Left Join dbo.IW_glGeneralLedger 
        On IW_glGeneralLedger.FeatureID = dbo.CMS_Features.FeatureSysID 
        Left Join dbo.IW_glSubChildAccount 
        On dbo.IW_glSubChildAccount.glSubChildAccountID = dbo.IW_glGeneralLedger.glSubChildAccountSysID
        Left Join dbo.IW_glAccountGroup 
        On dbo.IW_glAccountGroup.glAccountGroupID = dbo.IW_glSubChildAccount.glAccountGroupSysID
        Left Join dbo.IW_BankRegister 
        On dbo.IW_BankRegister.BankRegisterSysID = dbo.IW_glGeneralLedger.BankRegisterID
        Left Join dbo.IW_BankRegisterStatus 
        On dbo.IW_BankRegisterStatus.BankRegisterStatusSysID = dbo.IW_BankRegister.BankRegisterStatusID
        **Left Join (Select Distinct dbo.DTE_get_month_end(dt) as EndOfMonth 
            From IW_Calendar 
            Where dt Between '3/1/2004' 
            and @TransactionEndDate) as dates 
        on 1=1**
        Left Join dbo.IW_ReinsuranceTreaty 
        On dbo.IW_ReinsuranceTreaty.TreatySysID = IW_glGeneralLedger.PolicyTreatyID     
        Where dbo.IW_glGeneralLedger.TransactionDate Between '1/1/2004 00:00:00' And EndOfMonth
        And dbo.IW_glAccountGroup.Code In ('RESERVEINDEMNITY')  
        And (
          (dbo.IW_glGeneralLedger.BankRegisterID Is Null) 
          Or (
          (IW_BankRegister.PrintedDate Between '1/1/2004 00:00:00' And EndOfMonth Or dbo.IW_glGeneralLedger.BankRegisterID = 0)
             And 
            (dbo.IW_BankRegisterStatus.EnumValue In ('Approved','Outstanding','Cleared','Void') Or dbo.IW_glGeneralLedger.BankRegisterID = 0))
        )
    Group By TreatyName, dbo.CMS_Claims.ClaimSysID, FeatureSysID, EndOfMonth
    Having sum(IW_glGeneralLedger.TransactionAmount)  <> 0
) As Data
Group By TreatyName,EndOfMonth
Order By EndOfMonth, TreatyName

此嵌套的SQL代码仅在名为EndOfMonth的列中提供了月末值的表,这就是我要解决的问题:

Select Distinct dbo.DTE_get_month_end(dt) as EndOfMonth 
        From IW_Calendar 
        Where dt Between '3/1/2004' 
        and @TransactionEndDate

请使用以下方法提高查询性能。

  1. 使用临时表。 (在必要的条件下将相关数据加载到临时表中,然后联接)。
  2. 对表使用聚集索引和非聚集索引。
  3. 创建多列索引。
  4. 索引ORDER-BY / GROUP-BY / DISTINCT列以获得更好的响应时间。
  5. 使用参数化查询。
  6. 相应地使用查询提示。

    NOLOCK:在数据被锁定的情况下,这告诉SQL Server从最后一个已知的可用值(也称为脏读取)读取数据。 由于可以使用一些旧值和一些新值,因此数据集可能包含不一致之处。 不要在数据质量很重要的任何地方使用此功能。

    重新编译:将其添加到查询的末尾将导致每次执行该查询时都生成一个新的执行计划。 不应在经常执行的查询上使用此方法,因为优化查询的成本并非微不足道。 但是,对于不经常使用的报告或流程,这可能是避免不必要的计划重用的有效方法。 当统计数据过时或发生参数嗅探时,通常将其用作绷带。

MERGE / HASH / LOOP:这告诉查询优化器将特定类型的联接用作联接操作的一部分。 这是超级风险,因为最佳连接将随着数据,架构和参数随时间的变化而变化。 尽管这可能会立即解决问题,但它会引入技术债务的一种元素,这种隐患会一直存在,直到提示出现为止。

OPTIMIZE FOR: Can specify a parameter value to optimize the query for. This is often used when we want performance to be controlled for a very common use case so that outliers do not pollute the plan cache. Similar to join hints, this is fragile and when business logic changes, this hint usage may become obsolete.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM