這裏有兩個問題。每秒2,000輛車的SQL MERGE時CPU使用率高
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();
}
}
請檢查執行計劃重用... – Devart
將所有行上傳到db,然後一次對所有行進行合併。 –
你是否在調用這個腳本2000次?您應該創建一個Type Userdefined表。填充此類型並將其傳遞給存儲過程。這樣你只需要1次合併 –