【问题标题】:SQL Server query optimization for stored procedure存储过程的 SQL Server 查询优化
【发布时间】:2017-01-17 02:33:28
【问题描述】:

我需要提高 SQL Server 2014 中存储过程的性能。

这是我的程序,我想优化这个程序,因为它运行缓慢。

谁能用一些例子来解释一下,哪种查询在什么情况下更好?

CREATE PROCEDURE [dbo].[sp_Customer_SendMoney] 
    @CustomerId bigint,    
    @MobileNo nvarchar(15),    
    @Amount money,    
    @Comment nvarchar(250),    
    @PassPhrase nvarchar(50),
    @Type varchar(50) = null    
AS
BEGIN
    DECLARE @returnCode INT 
    DECLARE @RetVal BIGINT, @CustomerBalance MONEY,
            @CustomerMoneyRequestedId BIGINT, 
            @ToCustomerId BIGINT = 0,
            @TransactionId BIGINT, @CustomerAccount BIGINT,    
            @FromCustomerBalance MONEY = 0,
            @ToCustomerBalance MONEY = 0   

    IF EXISTS (SELECT Id FROM Customer 
               WHERE Id = @CustomerId AND IsDeleted = 0 AND IsActive = 1)    
    BEGIN
        SELECT 
            @CustomerBalance = Balance 
        FROM
            Customer 
        WHERE 
            Id = @CustomerId AND IsDeleted = 0 AND IsActive = 1 
       select @ToCustomerId = Id, @CustomerAccount = AccountNo,@ToCustomerBalance=Balance From Customer where convert(nvarchar,DecryptByPassPhrase(@PassPhrase, MobileNo)) = @MobileNo  and IsDeleted = 0 and IsActive = 1    
            if(@ToCustomerId > 0)
        begin
         if( lower(isnull(@Type,'regular')) <> 'suspention')
         begin
          set @ToCustomerBalance=@ToCustomerBalance+@Amount
         end
        END

        set @FromCustomerBalance=@CustomerBalance-@Amount
        if((@CustomerBalance > 0) and (@CustomerBalance >= @Amount) )    
        Begin     
           BEGIN TRAN TxnsenMoney
           BEGIN TRY 
            select @TransactionId = TransactionW2W+1 from MstGenerateTransactionID 
            where  [year]=datepart(yyyy,getdate()) and [month]=DATENAME(month,getdate())

            update MstGenerateTransactionID set TransactionW2W= @TransactionId 
            where  [year]=datepart(yyyy,getdate()) and [month]=DATENAME(month,getdate())
           --set @TransactionId = CONVERT(bigint,replace(convert(varchar, getdate(),111),'/','') + replace(convert(varchar, getdate(),114),':',''))       
        IF(@ToCustomerId > 0)    
        BEGIN
       --Update sender Customer
       update Customer set Balance = Balance - @Amount  where Id = @CustomerId    
       --Update receiver Customer
       if(lower(isnull(@Type,'regular')) <> 'suspention')
        begin
         update Customer set Balance = Balance + @Amount  where Id = @ToCustomerId   
        end  
       else
        begin
         update Customer set SuspentionAccount = isnull(SuspentionAccount,0) + @Amount  where Id = @ToCustomerId   
        end  

       INSERT INTO [TransactionW2W]    
        ([TransactionId]    
        ,[FromCustomerId]    
        ,[ToCustomerId]    
        ,[MobileNo]    
        ,[Amount]    
        ,[Comments]    
        ,[CreatedOn]
        ,[FromCustomerBalance]
        ,[ToCustomerBalance])    
        VALUES    
        (@TransactionId    
        ,@CustomerId    
        ,@ToCustomerId    
        ,@MobileNo    
        ,@Amount    
        ,@Comment    
        ,GETDATE()
        ,@FromCustomerBalance
        ,@ToCustomerBalance)                     

        End    --end IF @ToCustomerId > 0
        ELSE    
        BEGIN 
       --Update sender Customer              
       update Customer set Balance = Balance - @Amount where Id = @CustomerId    
       --print 'ELSE'
       INSERT INTO [TransactionW2W]    
       ([TransactionId]    
       ,[FromCustomerId]    
       ,[ToCustomerId]    
       ,[MobileNo]    
       ,[Amount]    
       ,[Comments]    
       ,[CreatedOn]
       ,[FromCustomerBalance])    
       VALUES    
       (@TransactionId    
       ,@CustomerId    
       ,@ToCustomerId    
       ,@MobileNo    
       ,@Amount    
       ,@Comment    
       ,GETDATE()
       ,@FromCustomerBalance)     

       INSERT INTO [NewCustomer]    
         ([FromCustomerId]    
         ,[MobileNo]    
         ,[Amount]    
         ,[CreatedOn]   
           )    
         VALUES    
         (@CustomerId    
         ,@MobileNo    
         ,@Amount    
         ,GETDATE()
          )    
        END --end ELSE @ToCustomerId > 0

     print @RetVal


      IF(@@TRANCOUNT >0 )    
         begin    
      set @RetVal = @TransactionId 
      print @RetVal      
         end    
         else    
         begin    
      RAISERROR('records not executed',16,1)    
         END
      COMMIT TRAN TxnsenMoney    
      END TRY  
      BEGIN CATCH 
      ROLLBACK TRAN TxnsenMoney
      set @RetVal = -1
      declare @error varchar(max)
      set @error= ERROR_MESSAGE()
     -- RAISERROR(@error,16,1) 
     print @error
      END CATCH     
    select @RetVal   
    End 
    END
    End

【问题讨论】:

  • 如果此过程有效但只需要优化,那么它非常适合我们的姊妹网站Code Review
  • 旁注:您应该为您的存储过程使用sp_ 前缀。微软有reserved that prefix for its own use (see Naming Stored Procedures),你确实会在未来某个时候冒着名称冲突的风险。 It's also bad for your stored procedure performance。最好只是简单地避免 sp_ 并使用其他东西作为前缀 - 或者根本不使用前缀!
  • 您需要同时查看查询计划和统计信息 io 输出。您还可以使用计划缓存中的性能指标。如果您希望有人提供帮助,您还需要包含您的表和索引结构。没有任何细节,只是猜测问题出在哪里。

标签: sql-server optimization


【解决方案1】:
CREATE PROCEDURE [dbo].[sp_Customer_SendMoney] 
    @CustomerId bigint,    
    @MobileNo nvarchar(15),    
    @Amount money,    
    @Comment nvarchar(250),    
    @PassPhrase nvarchar(50),
    @Type varchar(50) = null    
    AS    
    Begin    
       DECLARE @returnCode INT ,@RetVal bigint,@CustomerBalance money, @CustomerMoneyRequestedId bigint,@ToCustomerId bigint = 0,@TransactionId bigint,@CustomerAccount bigint,    
               @FromCustomerBalance money=0,@ToCustomerBalance money=0   

                IF EXISTS (select Id from Customer WITH(NOLOCK) where Id = @CustomerId and IsDeleted = 0 and IsActive = 1)  Begin    

                select @CustomerBalance = Balance from Customer WITH(NOLOCK) where Id = @CustomerId and IsDeleted = 0 and IsActive = 1 
                select @ToCustomerId = Id, @CustomerAccount = AccountNo,@ToCustomerBalance=Balance From Customer WITH(NOLOCK) 
                where convert(nvarchar,DecryptByPassPhrase(@PassPhrase, MobileNo)) = @MobileNo  and IsDeleted = 0 and IsActive = 1    
                    IF(@ToCustomerId > 0)
                        BEGIN
                        if( lower(isnull(@Type,'regular')) <> 'suspention')
                        BEGIN
                        SET @ToCustomerBalance=@ToCustomerBalance+@Amount
                    END
                END

        SET @FromCustomerBalance=@CustomerBalance-@Amount

       if((@CustomerBalance > 0) and (@CustomerBalance >= @Amount) )    
        Begin     
           BEGIN TRAN TxnsenMoney
                   BEGIN TRY 
                    SELECT  @TransactionId = TransactionW2W+1 
                    FROM    MstGenerateTransactionID  WITH(NOLOCK)
                    WHERE   [year]=datepart(yyyy,getdate()) and [month]=DATENAME(month,getdate())

                    update MstGenerateTransactionID set TransactionW2W= @TransactionId 
                    where  [year]=YEAR(GETDATE()) and [month]= MONTH(GETDATE())

               --set @TransactionId = CONVERT(bigint,replace(convert(varchar, getdate(),111),'/','') + replace(convert(varchar, getdate(),114),':',''))       
        IF(@ToCustomerId > 0)  BEGIN
       --Update sender Customer
             UPDATE Customer set Balance = Balance - @Amount  where Id = @CustomerId    
       --Update receiver Customer

        if(lower(isnull(@Type,'regular')) <> 'suspention') BEGIN 

             UPDATE Customer set Balance = Balance + @Amount  where Id = @ToCustomerId   

       END ELSE BEGIN 

           UPDATE Customer set SuspentionAccount = isnull(SuspentionAccount,0) + @Amount  where Id = @ToCustomerId   
       END  

       INSERT INTO [TransactionW2W]    
                  ([TransactionId] ,[FromCustomerId],[ToCustomerId] ,[MobileNo] ,[Amount],[Comments],[CreatedOn],[FromCustomerBalance],[ToCustomerBalance])    

       SELECT      @TransactionId ,@CustomerId ,@ToCustomerId ,@MobileNo ,@Amount ,@Comment,GETDATE(),@FromCustomerBalance ,@ToCustomerBalance                   

        END    --end IF @ToCustomerId > 0
        ELSE BEGIN 
           --Update sender Customer              
             UPDATE Customer set Balance = Balance - @Amount where Id = @CustomerId    
           --print 'ELSE'
             INSERT INTO [TransactionW2W]    
                       ([TransactionId] ,[FromCustomerId],[ToCustomerId] ,[MobileNo] ,[Amount] ,[Comments] ,[CreatedOn],[FromCustomerBalance])    

            SELECT @TransactionId ,@CustomerId  ,@ToCustomerId ,@MobileNo ,@Amount ,@Comment ,GETDATE() ,@FromCustomerBalance

            INSERT INTO [NewCustomer]    
                   ([FromCustomerId] ,[MobileNo] ,[Amount] ,[CreatedOn] )    

            SELECT @CustomerId,@MobileNo ,@Amount,GETDATE()

        END --end ELSE @ToCustomerId > 0

     print @RetVal


      IF(@@TRANCOUNT >0 )BEGIN
          set @RetVal = @TransactionId 
          print @RetVal      
     END ELSE BEGIN 
                  RAISERROR('records not executed',16,1)    
      END

      COMMIT TRAN TxnsenMoney    
      END TRY  

      BEGIN CATCH 

     ROLLBACK TRAN TxnsenMoney
      SET @RetVal = -1
      DECLARE @error varchar(max)
      SET @error= ERROR_MESSAGE()
     -- RAISERROR(@error,16,1) 
     print @error
      END CATCH     
    select @RetVal   
    End 
    END
    End

【讨论】:

  • Hii Radha 我在桌子上做了 WITH(NOLOCK) 更改。如果有任何锁定在桌子上的情况,您可以快速获取
  • 使用 NOLOCK 通常是个坏主意。它可能有不同类型的不良副作用
  • YES James Z But Temporary I think to give solution
  • 这真的不是我所说的解决方案。这是一个丑陋的 hack,可能会提高性能,但现在或以后也可能导致严重的问题。在不知道问题是什么的情况下,只是随机建议 NOLOCK 不是要走的路。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多