删除子查询以提高性能

时间:2013-11-20 18:43:25

标签: performance sql-server-2008

我有一个大查询,返回大约10,000行,执行大约需要15-20秒。这是一个遗留查询,我们希望提高性能。我们使用4-5内部连接和子查询。

我在执行计划中看到子查询/或条件正在创建惰性线轴,我想删除它。

您能否告诉我如何删除额外条件并提高查询性能。

SELECT
        mc.OTCCustomerID,
        'L' +  CONVERT(VARCHAR, MC.custlevel) AS Custlevel,
        @CustomerNbr,
        @ParentNumber,
        OTC1.ParentNumber AS GParent,
        OINV.DisputeCnt,
        OINV.Matter,
        OINV.MatterDesc,
        OINV.MatterTrust,
        OINV.TransactionNbr,
        OINV.TransactionDt,
        OINV.TransactionDueDt,
        OINV.NextActionDt,
        OINV.InvoiceStatusId,
        OINV.RemainingBalance,
        OINV.TransactionCurrencyCd,
        OINV.RemainingTransactionBalance,
        OINV.Days,
        OINV.BillingTmkNm,
        OINV.SupervisingTmk,
        OINV.ClientPartnerNm,
        LEFT(MC.customernm,20)    AS CustomerNm,
        OINV.IsTransactionReopen,
        OINV.IsBPTPCode,
        CD.PrimaryDecodeTxt AS outcome,
        OINV.TransactionType,
        OINV.CollectorComments,
        ISNULL(OINV.OTCInvoiceDetailsID,0) AS OTCInvoiceDetailsID,
        OINV.BalanceDue,
        OINV.Amount,
        OINV.CheckNbr,
        OINV.ExpectedDepositDt

FROM    dbo.OTCCustomer MC WITH( NOLOCK)
JOIN    dbo.OTCInvoiceDetails OINV WITH( NOLOCK)    
    ON  MC.OTCCUSTOMERID            = OINV.OTCCUSTOMERID
JOIN    dbo.CODEDETAIL CD WITH( NOLOCK)    
    ON  OINV.CollectionEffortOutComeID= CD.ID
JOIN    dbo.PrioritizationTypeFilter  PTF WITH( NOLOCK)    
    ON  OINV.TransactionType        = PTF.FilterName
JOIN    OTCCollectionStrategyFilter   CSF WITH( NOLOCK)
    ON  PTF.PrioritizationFilterID  = CSF.PrioritizationFilterID 
    AND CSF.CollectionStrategyId    = @strategyID
JOIN    dbo.OTCCustomer OTC1    
    ON  MC.ParentNumber             = OTC1.CustomerNbr 
    AND OINV.InvoiceStatusId        = 5 
    AND OINV.CSExecSource IS NOT NULL 
    AND (((SELECT DATEDIFF(dd,GETDATE(),OINV.NextActionDt)) <= 0) 
      OR
        ((OINV.CollectionEffortOutComeID IN (
            SELECT id
            FROM  dbo.codedetail WITH( NOLOCK)
            WHERE IsPTPEnabled = 1)) 
        AND (SELECT  DATEDIFF(dd,GETDATE(),OINV.ExpectedDepositDt)) <= 0) 
      OR
        (OINV.CollectionEffortOutComeID IN (
            SELECT id
            FROM   dbo.codedetail WITH( NOLOCK)
            WHERE  IsBPTPEnabled = 1))) 
    AND
       OINV.CollectionEffortOutComeID NOT IN (
            SELECT id
            FROM   dbo.codedetail WITH( NOLOCK)
            WHERE  PrimaryDecodeTxt = 'DL01-Dunning Letter 1' 
                OR PrimaryDecodeTxt = 'DL02-Dunning Letter 2' 
                OR PrimaryDecodeTxt = 'DL03-Dunning Letter 3')

2 个答案:

答案 0 :(得分:0)

您可以简化的一件事是您不要将DATEDIFF语句写为“SELECT ....”,您可以这么说:

AND DATEDIFF(dd, GETDATE(), OINV.NextActionDt) <= 0

甚至更简单:

AND OINV.NextActionDt < GETDATE()

其次,根据CodeDetail表的大小,您可能希望在执行其他操作之前查询它。类似的东西:

;
WITH CodeDetailFoo AS (
 SELECT id, IsPTPEnabled, IsBPTPEnabled
 FROM    dbo.codedetail WITH ( NOLOCK )
 WHERE IsPTPEnabled = 1 OR IsBPTPEnabled = 1
)
<<PUT THE REST OF YOUR QUERY HERE and use CodeDetailFoo>>

“WITH”方法意味着表格会在前面而不是每行进行查询。

答案 1 :(得分:0)

我认为这应该更快,我没有办法检查语法,请检查

SELECT *
FROM
(
    SELECT
            mc.OTCCustomerID,
            'L' +  CONVERT(VARCHAR, MC.custlevel) AS Custlevel,
            @CustomerNbr,
            @ParentNumber,
            OTC1.ParentNumber AS GParent,
            OINV.DisputeCnt,
            OINV.Matter,
            OINV.MatterDesc,
            OINV.MatterTrust,
            OINV.TransactionNbr,
            OINV.TransactionDt,
            OINV.TransactionDueDt,
            OINV.NextActionDt,
            OINV.InvoiceStatusId,
            OINV.RemainingBalance,
            OINV.TransactionCurrencyCd,
            OINV.RemainingTransactionBalance,
            OINV.Days,
            OINV.BillingTmkNm,
            OINV.SupervisingTmk,
            OINV.ClientPartnerNm,
            LEFT(MC.customernm,20)    AS CustomerNm,
            OINV.IsTransactionReopen,
            OINV.IsBPTPCode,
            CD.PrimaryDecodeTxt AS outcome,
            OINV.TransactionType,
            OINV.CollectorComments,
            ISNULL(OINV.OTCInvoiceDetailsID,0) AS OTCInvoiceDetailsID,
            OINV.BalanceDue,
            OINV.Amount,
            OINV.CheckNbr,
            OINV.ExpectedDepositDt,
            CASE WHEN DATEDIFF(dd,GETDATE(),OINV.NextActionDt) <= 0 THEN 1 
                WHEN  (UDF_TBL.MY_IND = 2 AND OINV.CollectionEffortOutComeID = UDF_TBL.ID AND DATEDIFF(dd,GETDATE(),OINV.ExpectedDepositDt) <= 0) THEN 1
                WHEN (UDF_TBL.MY_IND = 1 AND OINV.CollectionEffortOutComeID = UDF_TBL.ID) THEN 1
                ELSE 0 END AS FILTER_IND

    FROM    dbo.OTCCustomer MC WITH( NOLOCK)
    JOIN    dbo.OTCInvoiceDetails OINV WITH( NOLOCK)    
        ON  MC.OTCCUSTOMERID            = OINV.OTCCUSTOMERID
    JOIN    dbo.CODEDETAIL CD WITH( NOLOCK)    
        ON  OINV.CollectionEffortOutComeID= CD.ID
    JOIN    dbo.PrioritizationTypeFilter  PTF WITH( NOLOCK)    
        ON  OINV.TransactionType        = PTF.FilterName
    JOIN    OTCCollectionStrategyFilter   CSF WITH( NOLOCK)
        ON  PTF.PrioritizationFilterID  = CSF.PrioritizationFilterID 
        AND CSF.CollectionStrategyId    = @strategyID
    JOIN    dbo.OTCCustomer OTC1    
        ON  MC.ParentNumber             = OTC1.CustomerNbr 
        AND OINV.InvoiceStatusId        = 5 
        AND OINV.CSExecSource IS NOT NULL
      AND OINV.CollectionEffortOutComeID NOT IN (
                SELECT id
                FROM   dbo.codedetail WITH( NOLOCK)
                WHERE  PrimaryDecodeTxt = 'DL01-Dunning Letter 1' 
                    OR PrimaryDecodeTxt = 'DL02-Dunning Letter 2' 
                    OR PrimaryDecodeTxt = 'DL03-Dunning Letter 3')  
    LEFT JOIN 
        (
            SELECT id, CASE WHEN IsBPTPEnabled = 1 THEN 1 WHEN IsPTPEnabled = 1 THEN 2 END AS MY_IND
            FROM  dbo.codedetail WITH( NOLOCK)
            WHERE IsPTPEnabled = 1 OR IsBPTPEnabled = 1
        ) AS UDF_TBL
      ON       OINV.CollectionEffortOutComeID = UDF_TBL.ID
 ) A 
WHERE FILTER_IND = 1