当SQL MERGE为每秒2,000辆时,CPU使用率很高

时间:2016-03-16 13:22:58

标签: sql-server merge sql-server-2012 sql-server-2014

这里有两个问题。

1)有没有人知道为什么在每秒合并2,000辆车时我的CPU使用率会很高?

2)好奇,有没有办法在没有高CPU使用率的情况下每秒合并10,000辆车?

//Table & Index syntax...
CREATE TABLE [dbo].[Dealer_SalesVehicles](
    [RawID] [bigint] IDENTITY(1,1) NOT NULL,
    [AccountID] [bigint] NOT NULL,
    [StockNumber] [nvarchar](50) NOT NULL,
    [Vin] [nvarchar](30) NOT NULL,
    [Year] [nvarchar](50) NOT NULL,
    [Make] [nvarchar](50) NOT NULL,
    [Model] [nvarchar](50) NOT NULL,
    [Style] [nvarchar](80) NOT NULL
 CONSTRAINT [PK_Dealer_SalesVehicles_AccountId_StockNumber_Vin] PRIMARY KEY CLUSTERED 
(
    [AccountID] ASC,
    [StockNumber] ASC,
    [Vin] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 100) ON [PRIMARY]
) ON [PRIMARY]

//Sql Query...
var sqlAsk = "";
var rowAffected = 0;
var errorSqlParameters = new List<Tuple<string, string>>(); ;

using (var dbConnection = new SqlConnection(this._databaseConnectionString))
{
   using (var dbCommand = dbConnection.CreateCommand())
   {
       sqlAsk = "";
       sqlAsk += " MERGE ";
       sqlAsk += "     TOP (1)[dbo].[Dealer_SalesVehicles] WITH(HOLDLOCK) AS t ";
       sqlAsk += "     USING ";
       sqlAsk += "         (SELECT ";
       sqlAsk += "             @parmAccountId, @parmStockNumber, @parmVin ";
       sqlAsk += "         ) ";
       sqlAsk += "         AS s ";
       sqlAsk += "         ( ";
       sqlAsk += "             [AccountID], [StockNumber], [VIN] ";
       sqlAsk += "         ) ";
       sqlAsk += "     ON(t.[AccountId] = s.[AccountId] AND t.[StockNumber] = s.[StockNumber] AND t.[Vin] = s.[Vin]) ";
       //#-- if matched, update existing record if right conditions are met(see Description in header)...
       sqlAsk += " WHEN MATCHED AND(t.[AccountId] = s.[AccountId]) AND t.[StockNumber] = s.[StockNumber] AND(t.[Vin] = s.[Vin]) THEN ";
       sqlAsk += "     UPDATE SET ";
       //AccountID...
       //StockNumber...
       //VIN...
       sqlAsk += "         t.[Year] = @parmYear, ";
       sqlAsk += "         t.[Make] = @parmMake, ";
       sqlAsk += "         t.[Model] = @parmModel, ";
       sqlAsk += "         t.[Style] = @parmStyle ";
       //#-- if not matched, add new record and set return values...
       sqlAsk += " WHEN NOT MATCHED THEN ";
       //#--http://stackoverflow.com/questions/1609208/need-help-with-the-merge-statement...
       //#--(Cannot use "s." or "t." here, 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")...
       sqlAsk += "     INSERT( ";
       //RawID...
       sqlAsk += "         [AccountID], [StockNumber], [VIN], ";
       sqlAsk += "         [Year], [Make], [Model], [Style] ";
       sqlAsk += "     ) ";
       sqlAsk += "     VALUES( ";
       sqlAsk += "         @parmAccountId, @parmStockNumber, @parmVin, ";
       sqlAsk += "         @parmYear, @parmMake, @parmModel, @parmStyle ";
       sqlAsk += "     ) ";
       sqlAsk += " ; ";  //#--required semicolon separator for MERGE....

       dbCommand.CommandTimeout = 60;
       dbCommand.CommandText = sqlAsk;
       dbCommand.Parameters.Clear();
       dbCommand.Parameters.Add(new SqlParameter("@parmAccountId", SqlDbType.BigInt)).Value = parmSqlSalesVehicleRequest.DealerBranchAccountId;
       dbCommand.Parameters.Add(new SqlParameter("@parmStockNumber", SqlDbType.NVarChar)).Value = parmSqlSalesVehicleRequest.StockNumber;
       dbCommand.Parameters.Add(new SqlParameter("@parmVin", SqlDbType.NVarChar)).Value = parmSqlSalesVehicleRequest.Vin;
       dbCommand.Parameters.Add(new SqlParameter("@parmYear", SqlDbType.NVarChar)).Value = parmSqlSalesVehicleRequest.Year;
       dbCommand.Parameters.Add(new SqlParameter("@parmMake", SqlDbType.NVarChar)).Value = parmSqlSalesVehicleRequest.Make;
       dbCommand.Parameters.Add(new SqlParameter("@parmModel", SqlDbType.NVarChar)).Value = parmSqlSalesVehicleRequest.Model;
       dbCommand.Parameters.Add(new SqlParameter("@parmStyle", SqlDbType.NVarChar)).Value = parmSqlSalesVehicleRequest.Style;

       foreach (SqlParameter sqlParameter in dbCommand.Parameters)
       {
           errorSqlParameters.Add(new Tuple<string, string>(sqlParameter.ParameterName, sqlParameter.Value.ToString()));
       }

       if (dbConnection.State == ConnectionState.Open) { dbConnection.Close(); }

       await dbConnection.OpenAsync();

       rowAffected = await dbCommand.ExecuteNonQueryAsync();
   }
}

1 个答案:

答案 0 :(得分:0)

创建一个存储过程:

CREATE PROCEDURE dbo.usp_Add
(
    @parmAccountId ...,
    @parmStockNumber
)
AS BEGIN

    SET NOCOUNT ON;

    MERGE TOP(1) dbo.Dealer_SalesVehicles WITH (HOLDLOCK) t
    USING (
        SELECT [AccountID] = @parmAccountId,
               [StockNumber] = @parmStockNumber,
               [VIN] = @parmVin
    ) s ON t.[AccountId] = s.[AccountId]
        AND t.[StockNumber] = s.[StockNumber]
        AND t.[Vin] = s.[Vin]
    WHEN MATCHED
        THEN UPDATE
            SET
                t.[year] = @parmYear,
                t.[Make] = @parmMake,
                t.[model] = @parmModel,
                t.[style] = @parmStyle
    WHEN NOT MATCHED
        THEN INSERT ([AccountID], [StockNumber], [VIN], [year], [Make], [model], [style])
        VALUES (@parmAccountId, @parmStockNumber, @parmVin, @parmYear, @parmMake, @parmModel, @parmStyle);

END
GO

从您的代码中执行此SP。