MERGE语句执行时间太长(仅适用于1条记录)。 (MS-SQL Server 2012)

时间:2014-07-02 15:29:09

标签: sql sql-server sql-server-2012

我遇到的问题是这个SQL Merge命令执行时间太长了吗?它还需要30秒以上。我们正在使用MS-SQL 2012 Server。

那么,有人能告诉我MERGE声明我做错了什么以及为什么?

...谢谢

/****** Object:  StoredProcedure [dbo].[spDealerAccount_VehicleSalesRecordReload]    Script Date: 07/02/2014 11:02:21 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- ============================================================================
-- Author:      ...
-- Create date: 07/01/2014
-- Description: 
--      Either creates new or updates existing vehicle inventory record.
--      Record is updated only if ***either*** of following are met:
--          - source AccountID exists
--          - source VIN exists
--          - both source AccountID & VIN exists having no duplicate unique vehicle
-- References:
--      http://technet.microsoft.com/en-us/library/bb510625.aspx
--      http://en.wikipedia.org/wiki/Upsert
--      http://weblogs.sqlteam.com/dang/archive/2009/01/31/UPSERT-Race-Condition-With-MERGE.aspx (for explanation of HOLDLOCK)
-- ============================================================================
ALTER PROCEDURE [dbo].[spDealerAccount_VehicleSalesRecordReload]
    @parmAccountId              [bigint], 
    @parmBitwiseAcceptedTotal   [bigint],
    @parmYear                   [nvarchar](50),
    @parmMake                   [nvarchar](50),
    @parmModel                  [nvarchar](50),
    @parmTrim                   [nvarchar](80),
    @parmVin                    [nvarchar](17),
    @parmSquishVin              [nvarchar](12),
    @parmVinValidationSkipped   [bit],
    @parmMileage                [int],
    @parmPurchaseDate           [date],
    @parmSaleDate               [date],
    @parmNumOfDays              [int],
    @parmSaleType               [nvarchar](1),
    @parmPurchaseAmount         [money],
    @parmRepairCostAmount       [money],
    @parmSaleAmount             [money],
    @parmTotalTradeAmount       [money],
    @parmGrossProfitAmount      [money],
    @parmZipcode                [nvarchar](50),
    @parmCity                   [nvarchar](50),
    @parmState                  [nvarchar](50),
    @parmRegion                 [nvarchar](50),
    @parmStockNumber            [nvarchar](50),
    @parmLocation               [nvarchar](150),
    @parmDataSourceFrom         [nvarchar](500),
    @parmImportedVersion        [int],
    @parmCondition              [nvarchar](50),
    @parmAccessories            [nvarchar](MAX),
    @parmEngineDetail           [nvarchar](50),
    @parmExteriorColor          [nvarchar](50) 
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from interfering with SELECT statements.
    SET NOCOUNT ON;

    MERGE 
        INTO [dbo].[tblDealerSalesVehicles] WITH (HOLDLOCK) AS t
        USING [dbo].[tblDealerSalesVehicles] AS s
        ON (t.[AccountId] = s.[AccountId] AND t.[Vin] = s.[Vin])
    --  
    -- if matched, update existing record if right conditions are met (see Description in header)   
    WHEN MATCHED THEN
        UPDATE SET 
            --RawID...
            --AccountID...
            t.[BitwiseAcceptedTotal] = @parmBitwiseAcceptedTotal, 
            t.[Year] = @parmYear,
            t.[Make] = @parmMake,
            t.[Model] = @parmModel,
            t.[Trim] = @parmTrim,
            --VIN...
            --SquishVin...
            --[VinValidationSkipped...
            t.[Mileage] = @parmMileage,
            t.[StockDate] = @parmPurchaseDate,
            t.[SoldDate] = @parmSaleDate,
            t.[NumOfDays] = @parmNumOfDays,
            t.[SaleType] = @parmSaleType,
            t.[PurchPrice] = @parmPurchaseAmount,
            t.[RepairCost] = @parmRepairCostAmount,
            t.[SalePrice] = @parmSaleAmount,
            t.[TotalTrade] = @parmTotalTradeAmount,
            t.[GrossProfit] = @parmGrossProfitAmount,
            t.[Zipcode] = @parmZipcode,
            t.[City] = @parmCity,
            t.[State] = @parmState,
            t.[Region] = @parmRegion,
            t.[StockNo] = @parmStockNumber,
            t.[Location] = @parmLocation,
            t.[DataSourceFrom] = @parmDataSourceFrom,
            t.[ImportedVersion] = @parmImportedVersion,
            t.[ModifiedDate] = GETDATE(),
            --ImportedDate...
            t.[TimeStamp] = GETDATE()
    --             
    -- if not matched, add new record and set return values
    WHEN NOT MATCHED THEN   
         --http://stackoverflow.com/questions/1609208/need-help-with-the-merge-statement...
        --(Cannot use "s." or "t." for source or target table-name-abbreviation cuz "Columns name in the insert list can only refer to the target table, so the parser doesn't expect to see a table alias there, wouldn't know how to resolve it. It sees "column1", it knows it belongs to the target table. It sees "table1.column1", it doesn't know what "table1" means. "table1" is out of scope, so to speak")...
        INSERT (
            --RawID...
            [AccountID], [BitwiseAcceptedTotal],
            [Year], [Make], [Model], [Trim], [VIN], [SquishVin], [VinValidationSkipped],
            [Mileage], [StockDate], [SoldDate], [NumOfDays], [SaleType],
            [PurchPrice], [RepairCost], [SalePrice], 
            [TotalTrade], [GrossProfit], 
            [Zipcode], [City], [State], [Region],
            [StockNo], [Location], 
            [DataSourceFrom], [ImportedVersion], [ModifiedDate], [ImportedDate], [TimeStamp]
        ) 
        VALUES (
            @parmAccountId, @parmBitwiseAcceptedTotal,
            @parmYear, @parmMake, @parmModel, @parmTrim, @parmVin, @parmSquishVin, @parmVinValidationSkipped,
            @parmMileage, @parmPurchaseDate, @parmSaleDate, @parmNumOfDays, @parmSaleType,
            @parmPurchaseAmount, @parmRepairCostAmount, @parmSaleAmount,  
            @parmTotalTradeAmount, @parmGrossProfitAmount,  
            @parmZipcode, @parmCity, @parmState, @parmRegion, 
            @parmStockNumber, @parmLocation, 
            @parmDataSourceFrom, @parmImportedVersion, NULL, GETDATE(), GETDATE()
        )
    ; -- required semicolon separator for MERGE

    RETURN @@ERROR; 
END

1 个答案:

答案 0 :(得分:5)

我认为您的MERGE声明没有达到预期效果。你有相同的源和目标,没有参数的链接,所以这一点:

MERGE
    INTO [dbo].[tblDealerSalesVehicles] WITH (HOLDLOCK) AS t
    USING [dbo].[tblDealerSalesVehicles] AS s
    ON (t.[AccountId] = s.[AccountId] AND t.[Vin] = s.[Vin])

将匹配每个现有记录并使用您的参数进行更新。你可能想要使用类似的东西:

MERGE 
    INTO [dbo].[tblDealerSalesVehicles] WITH (HOLDLOCK) AS t
    USING (VALUES (@parmAccountId, @ParamVin)) AS s (AccountID, Vin)
    ON (t.[AccountId] = s.[AccountId] AND t.[Vin] = s.[Vin])
WHEN MATCHED THEN
    UPDATE SET 
  ....etc