【问题标题】:Tweaking Stored Procedure for High Performance across 300,000+ records调整存储过程以实现超过 300,000 条记录的高性能
【发布时间】:2016-02-13 01:52:12
【问题描述】:

我正在尝试构建一个用于 jQuery DataTables 前端 API 的 T-SQL 存储过程。前端 UI 为调用过程提供 orderby、过滤器、显示起始行和显示长度,如下所示。

为了提高性能,我在以下查询中是否遗漏了什么?

我需要向最终用户显示所有列,但我只需要 @NumberOfRowsToTake 参数中提供的行。

感谢您的宝贵时间。

CREATE PROCEDURE [dbo].[usp_Bank_GetAccounts_Paged]
    @SortDirection VARCHAR(4) = 'ASC'
    ,@SortColumn VARCHAR(50) = 'Lead_ID'
    ,@StartingRow INT = 1
    ,@NumOfRowsToTake INT = 5
    ,@Lead_ID INT = NULL
    ,@Account_ID BIGINT = NULL
    ,@Organization VARCHAR(100) = NULL
    ,@LeadNumber VARCHAR(20) = NULL
    ,@Source VARCHAR(50) = NULL
    ,@LeadReceivedDateBeg DATE = NULL
    ,@LeadReceivedDateEnd DATE = NULL
    ,@CalenderYear INT = NULL
    ,@RefundAvailableForRecoveryLowest MONEY = NULL
    ,@RefundAvailableForRecoveryHighest MONEY = NULL
    ,@ReasonForReferral VARCHAR(255) = NULL
    ,@CustomerNumber VARCHAR(11) = NULL
    ,@AccountLastName VARCHAR(20) = NULL
    ,@AccountFirstName VARCHAR(20) = NULL
    ,@NameOnRefundCheck VARCHAR(40) = NULL
    ,@Address VARCHAR(80) = NULL
    ,@City VARCHAR(20) = NULL
    ,@State VARCHAR(10) = NULL
    ,@ZipCode VARCHAR(10) = NULL
    ,@RTN VARCHAR(10) = NULL
    ,@ACCTNumber VARCHAR(20) = NULL
    ,@DebitCardNumber VARCHAR(20) = NULL
    ,@RefundClaimedLowest MONEY = NULL
    ,@RefundClaimedHighest MONEY = NULL
    ,@TreasuryCheckNumber VARCHAR(15) = NULL
    ,@Results VARCHAR(15) = NULL
    ,@SuspenseStatus VARCHAR(20) = NULL
    ,@FundsRequestedOrgLowest MONEY = NULL
    ,@FundsRequestedOrgHighest MONEY = NULL
    ,@FundsReturnedCustomerLowest MONEY = NULL
    ,@FundsReturnedCustomerHighest MONEY = NULL
    ,@VoucherOrMemoApplied VARCHAR(8) = NULL
    ,@Current_User_Name VARCHAR(5) = NULL
    ,@AssigneeFirstName VARCHAR(25) = NULL
    ,@AssigneeLastName VARCHAR(30) = NULL
    ,@AssigneeFullName VARCHAR(64) = NULL
    ,@Assignee_Site VARCHAR(10) = NULL
    ,@Current_Status_ID SMALLINT = NULL
    ,@Status_Name VARCHAR(20) = NULL
    ,@comment VARCHAR(255) = NULL
    ,@OriginalDepositDateBeg DATE = NULL
    ,@OriginalDepositDateEnd DATE = NULL
    ,@OriginalDepositAmountLowest MONEY = NULL
    ,@OriginalDepositAmountHighest MONEY = NULL
AS
BEGIN
    ; WITH ACCOUNTS AS 
    (
        SELECT TOP 99.9999999 PERCENT 
            [A].[Lead_ID]
            ,[A].[Account_ID]
            ,[L].[Organization]
            ,[L].[Lead_Number]
            ,[L].[Source]
            ,[L].[Lead_Received_Date]
            ,[A].[Calender_Year]
            ,[A].[Amount_To_Recover]
            ,[A].[Reason_For_Referral]
            ,[A].[CustomerNumber]
            ,[A].[Last_Name] AS [AccountLastName]
            ,[A].[First_Name] AS [AccountFirstName]
            ,[A].[Name_On_Refund]
            ,[A].[Address]
            ,[A].[City]
            ,[A].[State]
            ,[A].[Zip_Code]
            ,[A].[RTN]
            ,[A].[Audit_Number]
            ,[A].[Scan_Number]
            ,[A].[Amount_Claimed]
            ,[A].[Building_Number]
            ,[A].[Results]
            ,[A].[Date_Voucher_Sent]
            ,[A].[Return_ID_Number]
            ,[A].[Suspense_Status]
            ,[A].[Funds_Requested]
            ,[A].[Funds_Actually_Given]
            ,[A].[Voucher_or_Memo_Applied]
            ,[U].[SEID] AS [Current_User_Name]
            ,[U].[First_Name] AS [AssigneeFirstName]
            ,[U].[Last_Name] AS [AssigneeLastName]
            ,[U].[Last_Name] + ', ' + [U].[First_Name] + '(' + [U].[SEID] + ')' AS [AssigneeFullName]
            ,[U].[Site] AS [Assignee_Site]
            ,[A].[Current_Status_ID]
            ,[S].[Status_Name]
            ,[A].[Deleted_Date]
            ,[A].[comment]
            ,[A].[Original_Deposit_Date]
            ,[A].[Original_Deposit_Amount]
            ,ROW_NUMBER() OVER (
                ORDER BY CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Lead_ID' THEN [A].[Lead_ID] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Lead_ID' THEN [A].[Lead_ID] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Account_ID' THEN [A].[Account_ID] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Account_ID' THEN [A].[Account_ID] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Organization' THEN [L].[Organization] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Organization' THEN [L].[Organization] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Lead_Number' THEN [L].[Lead_Number] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Lead_Number' THEN [L].[Lead_Number] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Source' THEN [L].[Source] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Source' THEN [L].[Source] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Lead_Received_Date' THEN [L].[Lead_Received_Date] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Lead_Received_Date' THEN [L].[Lead_Received_Date] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Calender_Year' THEN [A].[Calender_Year] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Calender_Year' THEN [A].[Calender_Year] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Amount_To_Recover' THEN [A].[Amount_To_Recover] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Amount_To_Recover' THEN [A].[Amount_To_Recover] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Amount_To_Recover' THEN [A].[Reason_For_Referral] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Amount_To_Recover' THEN [A].[Reason_For_Referral] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'CustomerNumber' THEN [A].[CustomerNumber] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'CustomerNumber' THEN [A].[CustomerNumber] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'AccountLastName' THEN [A].[Last_Name] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'AccountFirstName' THEN [A].[First_Name] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Name_On_Refund' THEN [A].[Name_On_Refund] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Name_On_Refund' THEN [A].[Name_On_Refund] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Address' THEN [A].[Address] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Address' THEN [A].[Address] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'City' THEN [A].[City] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'City' THEN [A].[City] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'State' THEN [A].[State] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'State' THEN [A].[State] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Zip_Code' THEN [A].[Zip_Code] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Zip_Code' THEN [A].[Zip_Code] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'RTN' THEN [A].[RTN] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'RTN' THEN [A].[RTN] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Audit_Number' THEN [A].[Audit_Number] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Audit_Number' THEN [A].[Audit_Number] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Scan_Number' THEN [A].[Scan_Number] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Scan_Number' THEN [A].[Scan_Number] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Amount_Claimed' THEN [A].[Amount_Claimed] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Amount_Claimed' THEN [A].[Amount_Claimed] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Results' THEN [A].[Results] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Results' THEN [A].[Results] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Date_Voucher_Sent' THEN [A].[Date_Voucher_Sent] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Date_Voucher_Sent' THEN [A].[Date_Voucher_Sent] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Return_ID_Number' THEN [A].[Return_ID_Number] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Return_ID_Number' THEN [A].[Return_ID_Number] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Suspense_Status' THEN [A].[Suspense_Status] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Suspense_Status' THEN [A].[Suspense_Status] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Funds_Requested' THEN [A].[Funds_Requested] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Funds_Requested' THEN [A].[Funds_Requested] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Funds_Actually_Given' THEN [A].[Funds_Requested] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Funds_Actually_Given' THEN [A].[Funds_Requested] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Voucher_or_Memo_Applied' THEN [A].[Voucher_or_Memo_Applied] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Voucher_or_Memo_Applied' THEN [A].[Voucher_or_Memo_Applied] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Current_User_Name' THEN [U].[SEID] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Current_User_Name' THEN [U].[SEID] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'AssigneeFirstName' THEN [U].[First_Name] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'AssigneeFirstName' THEN [U].[First_Name] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'AssigneeLastName' THEN [U].[Last_Name] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'AssigneeLastName' THEN [U].[Last_Name] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Assignee_Site' THEN [U].[Site] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Assignee_Site' THEN [U].[Site] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Current_Status_ID' THEN [A].[Current_Status_ID] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Current_Status_ID' THEN [A].[Current_Status_ID] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Status_Name' THEN [S].[Status_Name] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Status_Name' THEN [S].[Status_Name] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Deleted_Date' THEN [A].[Deleted_Date] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Deleted_Date' THEN [A].[Deleted_Date] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'comment' THEN [A].[comment] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'comment' THEN [A].[comment] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Original_Deposit_Date' THEN [A].[Original_Deposit_Date] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Original_Deposit_Date' THEN [A].[Original_Deposit_Date] END DESC
                    ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Original_Deposit_Amount' THEN [A].[Original_Deposit_Amount] END ASC
                    ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Original_Deposit_Amount' THEN [A].[Original_Deposit_Amount] END DESC
                ) AS [ROWNUM]
        FROM
            [dbo].[Bank_Account] AS [A] WITH (NOLOCK)
        INNER JOIN 
            [dbo].[Bank_Lead] AS [L] WITH (NOLOCK) ON [A].[Lead_ID] = [L].[Lead_ID]
        LEFT JOIN 
            [dbo].[Bank_ref_Status] AS [S] WITH (NOLOCK) ON [A].[Current_Status_ID] = [S].[Status_ID]
        LEFT JOIN 
            [dbo].[Bank_Assignee] AS [U] WITH (NOLOCK) ON [A].[Current_User_Name] = [U].[SEID]
        WHERE 
            (@Lead_ID IS NULL OR [A].[Lead_ID] = @Lead_ID) 
            AND (@Account_ID IS NULL OR [A].[Account_ID] = @Account_ID) 
            AND (@Organization IS NULL OR CHARINDEX(UPPER(@Organization), UPPER([L].[Organization])) > 0) 
            AND (@LeadNumber IS NULL OR CHARINDEX(UPPER(@LeadNumber), UPPER([L].[Lead_Number])) > 0) 
            AND (@Source IS NULL OR CHARINDEX(UPPER(@Source), UPPER([L].[Source])) > 0) 
            AND (@LeadReceivedDateBeg IS NULL OR [L].[Lead_Received_Date] >= @LeadReceivedDateBeg) 
            AND (@LeadReceivedDateEnd IS NULL OR [L].[Lead_Received_Date] <= @LeadReceivedDateEnd) 
            AND (@CalenderYear IS NULL OR [A].[Calender_Year] = @CalenderYear) 
            AND (@RefundAvailableForRecoveryLowest IS NULL OR [A].[Amount_To_Recover] >= @RefundAvailableForRecoveryLowest) 
            AND (@RefundAvailableForRecoveryHighest IS NULL OR [A].[Amount_To_Recover] <= @RefundAvailableForRecoveryHighest) 
            AND (@ReasonForReferral IS NULL OR CHARINDEX(UPPER(@ReasonForReferral), UPPER([A].[Reason_For_Referral])) > 0) 
            AND (@CustomerNumber IS NULL OR CHARINDEX(UPPER(@CustomerNumber), UPPER([A].[CustomerNumber])) > 0) 
            AND (@AccountLastName IS NULL OR CHARINDEX(UPPER(@AccountLastName), UPPER([A].[Last_Name])) > 0) 
            AND (@AccountFirstName IS NULL OR CHARINDEX(UPPER(@AccountFirstName), UPPER([A].[First_Name])) > 0) 
            AND (@NameOnRefundCheck IS NULL OR CHARINDEX(UPPER(@NameOnRefundCheck), UPPER([A].[Name_On_Refund])) > 0) 
            AND (@Address IS NULL OR CHARINDEX(UPPER(@Address), UPPER([A].[Address])) > 0) 
            AND (@City IS NULL OR CHARINDEX(UPPER(@City), UPPER([A].[City])) > 0) 
            AND (@State IS NULL OR CHARINDEX(UPPER(@State), UPPER([A].[State])) > 0) 
            AND (@ZipCode IS NULL OR CHARINDEX(UPPER(@ZipCode), UPPER([A].[Zip_Code])) > 0) 
            AND (@RTN IS NULL OR CHARINDEX(UPPER(@RTN), UPPER([A].[RTN])) > 0) 
            AND (@ACCTNumber IS NULL OR CHARINDEX(UPPER(@ACCTNumber), UPPER([A].[Audit_Number])) > 0) 
            AND (@DebitCardNumber IS NULL OR CHARINDEX(UPPER(@DebitCardNumber), UPPER([A].[Scan_Number])) > 0)
            AND (@RefundClaimedLowest IS NULL OR [A].[Amount_Claimed] >= @RefundClaimedLowest) 
            AND (@RefundClaimedHighest IS NULL OR [A].[Amount_Claimed] <= @RefundClaimedHighest) 
            AND (@TreasuryCheckNumber IS NULL OR CHARINDEX(UPPER(@TreasuryCheckNumber), UPPER([A].[Building_Number])) > 0) 
            AND (@Results IS NULL OR CHARINDEX(UPPER(@Results), UPPER([A].[Results])) > 0) 
            AND (@SuspenseStatus IS NULL OR CHARINDEX(UPPER(@SuspenseStatus), UPPER([A].[Suspense_Status])) > 0) 
            AND (@FundsRequestedOrgLowest IS NULL OR [A].[Funds_Requested] >= @FundsRequestedOrgLowest) 
            AND (@FundsRequestedOrgHighest IS NULL OR [A].[Funds_Requested] <= @FundsRequestedOrgHighest) AND (@FundsReturnedCustomerLowest IS NULL OR [A].[Funds_Actually_Given] >= @FundsReturnedCustomerLowest) AND (@FundsReturnedCustomerHighest IS NULL OR [A].[Funds_Actually_Given] <= @FundsReturnedCustomerHighest) AND (@VoucherOrMemoApplied IS NULL OR CHARINDEX(UPPER(@VoucherOrMemoApplied), UPPER([A].[Voucher_or_Memo_Applied])) > 0
                ) AND (@Current_User_Name IS NULL OR CHARINDEX(UPPER(@Current_User_Name), UPPER([U].[SEID])) > 0) AND (@AssigneeFirstName IS NULL OR CHARINDEX(UPPER(@AssigneeFirstName), UPPER([U].[First_Name])) > 0) AND (@AssigneeLastName IS NULL OR CHARINDEX(UPPER(@AssigneeLastName), UPPER([U].[Last_Name])) > 0) AND (@AssigneeFullName IS NULL OR CHARINDEX(UPPER(@AssigneeFullName), UPPER([U].[Last_Name] + ', ' + [U].[First_Name] + '(' + [U].[SEID] + ')')) > 0) AND (@Assignee_Site IS NULL OR CHARINDEX(UPPER(@Assignee_Site), UPPER([U].[Site])) > 0) AND (@Current_Status_ID IS NULL OR @Current_Status_ID = [A].[Current_Status_ID]) AND (@Status_Name IS NULL OR CHARINDEX(UPPER(@Status_Name), UPPER([S].[Status_Name])) > 0) AND ([A].Deleted_Date IS NULL) AND (@comment IS NULL OR CHARINDEX(UPPER(@comment), UPPER([A].[comment])) > 0) AND (@OriginalDepositDateBeg IS NULL OR [A].[Original_Deposit_Date] >= @OriginalDepositDateBeg) 
            AND (@OriginalDepositDateEnd IS NULL OR [A].[Original_Deposit_Date] <= @OriginalDepositDateEnd) AND (@OriginalDepositAmountLowest IS NULL OR [A].[Original_Deposit_Amount] >= @OriginalDepositAmountLowest) AND (@OriginalDepositAmountHighest IS NULL OR [A].[Original_Deposit_Amount] <= @OriginalDepositAmountHighest)
        ORDER BY CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Lead_ID' THEN [A].[Lead_ID] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Lead_ID' THEN [A].[Lead_ID] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Account_ID' THEN [A].[Account_ID] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Account_ID' THEN [A].[Account_ID] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Organization' THEN [L].[Organization] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Organization' THEN [L].[Organization] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Lead_Number' THEN [L].[Lead_Number] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Lead_Number' THEN [L].[Lead_Number] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Source' THEN [L].[Source] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Source' THEN [L].[Source] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Lead_Received_Date' THEN [L].[Lead_Received_Date] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Lead_Received_Date' THEN [L].[Lead_Received_Date] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Calender_Year' THEN [A].[Calender_Year] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Calender_Year' THEN [A].[Calender_Year] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Amount_To_Recover' THEN [A].[Amount_To_Recover] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Amount_To_Recover' THEN [A].[Amount_To_Recover] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Amount_To_Recover' THEN [A].[Reason_For_Referral] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Amount_To_Recover' THEN [A].[Reason_For_Referral] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'CustomerNumber' THEN [A].[CustomerNumber] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'CustomerNumber' THEN [A].[CustomerNumber] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'AccountLastName' THEN [A].[Last_Name] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'AccountFirstName' THEN [A].[First_Name] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Name_On_Refund' THEN [A].[Name_On_Refund] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Name_On_Refund' THEN [A].[Name_On_Refund] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Address' THEN [A].[Address] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Address' THEN [A].[Address] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'City' THEN [A].[City] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'City' THEN [A].[City] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'State' THEN [A].[State] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'State' THEN [A].[State] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Zip_Code' THEN [A].[Zip_Code] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Zip_Code' THEN [A].[Zip_Code] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'RTN' THEN [A].[RTN] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'RTN' THEN [A].[RTN] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Audit_Number' THEN [A].[Audit_Number] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Audit_Number' THEN [A].[Audit_Number] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Scan_Number' THEN [A].[Scan_Number] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Scan_Number' THEN [A].[Scan_Number] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Amount_Claimed' THEN [A].[Amount_Claimed] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Amount_Claimed' THEN [A].[Amount_Claimed] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Results' THEN [A].[Results] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Results' THEN [A].[Results] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Date_Voucher_Sent' THEN [A].[Date_Voucher_Sent] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Date_Voucher_Sent' THEN [A].[Date_Voucher_Sent] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Return_ID_Number' THEN [A].[Return_ID_Number] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Return_ID_Number' THEN [A].[Return_ID_Number] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Suspense_Status' THEN [A].[Suspense_Status] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Suspense_Status' THEN [A].[Suspense_Status] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Funds_Requested' THEN [A].[Funds_Requested] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Funds_Requested' THEN [A].[Funds_Requested] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Funds_Actually_Given' THEN [A].[Funds_Requested] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Funds_Actually_Given' THEN [A].[Funds_Requested] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Voucher_or_Memo_Applied' THEN [A].[Voucher_or_Memo_Applied] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Voucher_or_Memo_Applied' THEN [A].[Voucher_or_Memo_Applied] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Current_User_Name' THEN [U].[SEID] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Current_User_Name' THEN [U].[SEID] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'AssigneeFirstName' THEN [U].[First_Name] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'AssigneeFirstName' THEN [U].[First_Name] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'AssigneeLastName' THEN [U].[Last_Name] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'AssigneeLastName' THEN [U].[Last_Name] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Assignee_Site' THEN [U].[Site] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Assignee_Site' THEN [U].[Site] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Current_Status_ID' THEN [A].[Current_Status_ID] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Current_Status_ID' THEN [A].[Current_Status_ID] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Status_Name' THEN [S].[Status_Name] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Status_Name' THEN [S].[Status_Name] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Deleted_Date' THEN [A].[Deleted_Date] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Deleted_Date' THEN [A].[Deleted_Date] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'comment' THEN [A].[comment] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'comment' THEN [A].[comment] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Original_Deposit_Date' THEN [A].[Original_Deposit_Date] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Original_Deposit_Date' THEN [A].[Original_Deposit_Date] END DESC
            ,CASE WHEN UPPER(@SortDirection) = 'ASC' AND @SortColumn = 'Original_Deposit_Amount' THEN [A].[Original_Deposit_Amount] END ASC
            ,CASE WHEN UPPER(@SortDirection) = 'DESC' AND @SortColumn = 'Original_Deposit_Amount' THEN [A].[Original_Deposit_Amount] END DESC
        )
    SELECT [Lead_ID]
        ,[Account_ID]
        ,[Organization]
        ,[Lead_Number]
        ,[Source]
        ,[Lead_Received_Date]
        ,[Calender_Year]
        ,[Amount_To_Recover]
        ,[Reason_For_Referral]
        ,[CustomerNumber]
        ,[AccountLastName]
        ,[AccountFirstName]
        ,[Name_On_Refund]
        ,[Address]
        ,[City]
        ,[State]
        ,[Zip_Code]
        ,[RTN]
        ,[Audit_Number]
        ,[Scan_Number]
        ,[Amount_Claimed]
        ,[Building_Number]
        ,[Results]
        ,[Date_Voucher_Sent]
        ,[Return_ID_Number]
        ,[Suspense_Status]
        ,[Funds_Requested]
        ,[Funds_Actually_Given]
        ,[Voucher_or_Memo_Applied]
        ,[Current_User_Name]
        ,[AssigneeFirstName]
        ,[AssigneeLastName]
        ,[AssigneeFullName]
        ,[Assignee_Site]
        ,[Current_Status_ID]
        ,[Status_Name]
        ,[Deleted_Date]
        ,[comment]
        ,[Original_Deposit_Date]
        ,[Original_Deposit_Amount]
    FROM ACCOUNTS
    WHERE (@StartingRow IS NULL OR ([ROWNUM] BETWEEN @StartingRow AND ((@StartingRow - 1) + @NumOfRowsToTake)))
END
GO

【问题讨论】:

  • 动态order by 子句可能会导致一些意外结果(即缓存错误的查询计划)。你有什么确切的问题?我已经看到with recompile 确实有帮助,尽管并不理想。也许使用动态 sql 构建查询会更快——很难说。像往常一样,它只是取决于性能。
  • @speddes 我在 Web UI 前端有一个表,它需要显示来自相当大的数据库表的记录。我一次只需要显示一组记录;但我需要指定的所有列。理想情况下,人们可以对文本列进行部分搜索,动态排序(排序),然后对结果进行分页。

标签: sql sql-server database sql-server-2008 stored-procedures


【解决方案1】:

SP 永远不会像现在这样快;你要重写了。你可以用它做的唯一一件简单的事情就是尝试 WITH RECOMPILE/OPTION (RECOMPILE),这看起来像是一个讨厌的编译。

考虑阅读Erland Sommarskog's article Dynamic Search Conditions in T‑SQL,它详细讨论了这种一般情况。

老实说,按照您的结构方式,您可能应该查看sp_executesql 并将每个变量都作为参数传递给 sp_executesql。

这样,您至少会为每个参数组合获得一个专用的查询计划,并且不会有多余的废话。

在构建动态 SQL 语句时,仅使用您需要的 WHERE 和 ORDER BY 部分,但 不要连接直接传递给 SQL 本身的值(这将允许恶意用户进行 SQL 注入) ;将它们用作参数,或作为放入 SQL 块的 IF 语句的一部分。

然后摆脱你的非 SARGable JOINWHERE 部分,就像那些 CHARINDEX()s - 在 WHEREJOIN(或者甚至 ORDER BY,如果可能的话)子句中没有功能,请,然后您的索引就可以完成它们的工作了!

对于您的@StartingRow@NumRowsToTake 分页,请考虑升级到SQL Server 2012 或更高版本并阅读Aaron Bertrand 的Pagination with Offset Fetch;他在其中的一些选项上有一些很好的基准和指标。请注意,您甚至应该阅读 SQL Server 2008 的前几段,尤其是

根据表的索引、所需的列和选择的排序方法,分页可以相对轻松。如果您正在寻找“前”20 个客户并且聚集索引支持该排序(例如,IDENTITY 列或 DateCreated 列上的聚集索引),那么查询将非常有效。如果您需要支持需要非聚集索引的排序,特别是如果您有输出所需的列未被索引覆盖(如果没有支持索引,请不要介意),查询可能会变得更加昂贵。即使是相同的查询(使用不同的@PageNumber 参数)也会随着@PageNumber 的增大而变得更加昂贵——因为可能需要更多的读取来获取数据的“切片”。

【讨论】:

  • 快速说明——这篇文章是给SQL Server 2008的。使用 fetch and offset 是 2012 年引入的...除此之外,同意您的大多数 cmets。
  • 我还没有读过 Sommarskog 发表的那篇文章——+1,非常好的深度阅读。非常有用的 imo。
  • @Anti-weakpasswords 感谢您的 cmets;根据您所写的内容,我基本上应该构建动态 SQL,然后执行它?另外,我应该使用 LIKE 而不是 CHARINDEX?如果可能,我想支持部分字符串搜索。如果这会严重影响性能,那么我可以放弃它。
  • 尝试添加一个 recompile 选项 - 这会有所帮助。此外,所有这些案例都在计算 ROW_NUMBER - 为什么要在 ORDER BY 子句中重复案例列表?按 row_number 结果排序。
  • @ChrisK。 - 如果您想甚至考虑索引,只要通配符不在左侧,您就可以使用 LIKE;如果最左边的字符是通配符,则不能使用索引。另外,我强烈建议至少需要几个字符,因为 LIKE 'M%' 并没有真正的用处,尽管 LIKE 'MICH%' 可能有机会获得合理的结果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-09
  • 2013-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多