[英]Bulk insert is not working properly in Azure SQL Server
我無法使用C#webapi將大量數據插入Azure SQL Server數據庫
考慮
我想在SQL中插入60K>數據。 在我的本地SQL服務器中沒有問題,但在Azure SQL中它的連接超時
我的方法:(所有都在本地sql服務器上工作,但在Azure sql server中沒有)
1)嘗試使用EF逐個插入記錄(10000次約10分鍾,大部分超時)
2)嘗試使用批量插入擴展和EF 3)在SqlBulkCopy中嘗試
4)嘗試增加連接字符串中的連接超時
5)嘗試在Dbcontext中增加命令時間。
異常StackTrace
Execution Timeout Expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
System.Data.SqlClient.SqlException (0x80131904): Execution Timeout Expired. The timeout period elapsed prior to completion of the operation or the server is not responding. ---> System.ComponentModel.Win32Exception (0x80004005): The wait operation timed out
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
at System.Data.SqlClient.TdsParserStateObject.ReadSniError(TdsParserStateObject stateObj, UInt32 error)
at System.Data.SqlClient.TdsParserStateObject.ReadSniSyncOverAsync()
at System.Data.SqlClient.TdsParserStateObject.TryReadNetworkPacket()
at System.Data.SqlClient.TdsParserStateObject.TryPrepareBuffer()
at System.Data.SqlClient.TdsParserStateObject.TryReadByte(Byte& value)
at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
at System.Data.SqlClient.SqlBulkCopy.RunParser(BulkCopySimpleResultSet bulkCopyHandler)
at System.Data.SqlClient.SqlBulkCopy.CopyBatchesAsyncContinuedOnSuccess(BulkCopySimpleResultSet internalResults, String updateBulkCommandText, CancellationToken cts, TaskCompletionSource`1 source)
at System.Data.SqlClient.SqlBulkCopy.CopyBatchesAsyncContinued(BulkCopySimpleResultSet internalResults, String updateBulkCommandText, CancellationToken cts, TaskCompletionSource`1 source)
at System.Data.SqlClient.SqlBulkCopy.CopyBatchesAsync(BulkCopySimpleResultSet internalResults, String updateBulkCommandText, CancellationToken cts, TaskCompletionSource`1 source)
at System.Data.SqlClient.SqlBulkCopy.WriteToServerInternalRestContinuedAsync(BulkCopySimpleResultSet internalResults, CancellationToken cts, TaskCompletionSource`1 source)
at System.Data.SqlClient.SqlBulkCopy.WriteToServerInternalRestAsync(CancellationToken cts, TaskCompletionSource`1 source)
at System.Data.SqlClient.SqlBulkCopy.WriteToServerInternalAsync(CancellationToken ctoken)
at System.Data.SqlClient.SqlBulkCopy.WriteRowSourceToServerAsync(Int32 columnCount, CancellationToken ctoken)
at System.Data.SqlClient.SqlBulkCopy.WriteToServer(DataTable table, DataRowState rowState)
是否有任何解決方案或Azure中的任何配置要更改?
更新
用於批量插入的代碼
using (var dbConnection = new DBModel().Database.Connection as SqlConnection)
{
dbConnection?.Open();
using (var sqlBulkCopy = new SqlBulkCopy(dbConnection))
{
try
{
/* ColumnMapping
* Column is mapped to DB Column to DataTable Column
*
*/
sqlBulkCopy.EnableStreaming = true;
sqlBulkCopy.BulkCopyTimeout = 500;
sqlBulkCopy.DestinationTableName = "LogTable";
//dt is object of the Datatable
sqlBulkCopy.WriteToServer(dt);
}
catch (Exception ex)
{
}
}
}
我建議你將sqlBulkCopy.BatchSize
設置為合理的數量,而不是一次性插入所有內容。 根據您要插入的數據,嘗試從10.000開始,向上或向下工作,直到您對性能滿意為止。
編輯以獲得一些額外的說明:當您考慮批量大小時,您需要考慮到SqlBulkCopy不僅需要插入數據,還需要讀取和發送它 - 最后一部分可能是它在本地工作的原因SQL服務器,但不在Azure上 - 它還意味着,如果您正在使用大型數據集,則需要使用較低的批處理大小或相當高的BulkCopyTimeout設置,以允許每個批處理完成之前達到超時限制。
您可以在本文中閱讀有關批量大小的更多信息。 SqlBulkCopy的推薦批量大小是多少?
其他選擇:
我正在讀這篇文章,它可能只是因為你的插入到達了一個關鍵的DTU(數據庫事務處理單元,基本上是服務器組合資源的度量)使用點。
性能級別經過校准和管理,以提供運行數據庫工作負載所需的資源,達到所選服務層/性能級別允許的最大限制。 如果您的工作負載達到了CPU / Data IO / Log IO限制之一的限制,您將繼續以最大允許級別接收資源,但您可能會看到查詢的延遲增加 。 這些限制不會導致任何錯誤,只會導致工作負載減慢 ,除非減速變得非常嚴重以至於查詢開始超時 。
取自以下鏈接: https : //azure.microsoft.com/da-dk/blog/azure-sql-database-introduces-new-near-real-time-performance-metrics/
嘗試在監視DTU使用情況時再次啟動副本,並查看它是否在100(長期)時間內處於100%狀態。 如果是這種情況,您可能需要提高數據庫的定價層級別。
我在過去兩天一直在處理批量插入,這里是一個通用批量插入類,允許你排除一些列,如果發現DbGeography屬性,它將它轉換為SqlGeography:
public class BulkInsert<T> where T : class
{
#region Fields
private readonly LoggingService _logger = new LoggingService(typeof(BulkInsert<T>));
private string _connectionString;
private string _tableName;
private IEnumerable<string> _excludedPropertyNames;
private int _batchSize;
private IEnumerable<T> _data;
private DataTable _dataTable;
#endregion
#region Constructor
public BulkInsert(
string connectionString,
string tableName,
IEnumerable<T> data,
IEnumerable<string> excludedPropertyNames,
int batchSize = 1000)
{
if (string.IsNullOrEmpty(connectionString)) throw new ArgumentNullException(nameof(connectionString));
if (string.IsNullOrEmpty(tableName)) throw new ArgumentNullException(nameof(tableName));
if (data == null) throw new ArgumentNullException(nameof(data));
if (batchSize <= 0) throw new ArgumentOutOfRangeException(nameof(batchSize));
_connectionString = connectionString;
_tableName = tableName;
_batchSize = batchSize;
_data = data;
_excludedPropertyNames = excludedPropertyNames == null ? new List<string>() : excludedPropertyNames;
_dataTable = CreateCustomDataTable();
}
#endregion
#region Public Methods
public void Insert()
{
using (var connection = new SqlConnection(_connectionString))
{
connection.Open();
SqlTransaction transaction = connection.BeginTransaction();
using (var bulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.Default | SqlBulkCopyOptions.KeepIdentity, transaction))
{
bulkCopy.BatchSize = _batchSize;
bulkCopy.DestinationTableName = _tableName;
// Let's fix tons of mapping issues by
// Setting the column mapping in SqlBulkCopy instance:
foreach (DataColumn dataColumn in _dataTable.Columns)
{
bulkCopy.ColumnMappings.Add(dataColumn.ColumnName, dataColumn.ColumnName);
}
try
{
bulkCopy.WriteToServer(_dataTable);
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
transaction.Rollback();
connection.Close();
}
}
transaction.Commit();
}
}
#endregion
#region Private Helper Methods
private DataTable CreateCustomDataTable()
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
var table = new DataTable();
foreach (PropertyDescriptor prop in properties)
{
// Just include the not excluded columns
if (_excludedPropertyNames.All(epn => epn != prop.Name))
{
if (prop.PropertyType.Name == "DbGeography")
{
var type = typeof(SqlGeography);
table.Columns.Add(prop.Name, type);
}
else
{
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
}
}
}
foreach (T item in _data)
{
DataRow row = table.NewRow();
foreach (PropertyDescriptor prop in properties)
{
// Just include the values in not excluded properties
if (_excludedPropertyNames.All(epn => epn != prop.Name))
{
if (prop.PropertyType.Name == "DbGeography")
{
row[prop.Name] = SqlGeography.Parse(((DbGeography)prop.GetValue(item)).AsText()).MakeValid();
}
else
{
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
}
}
}
table.Rows.Add(row);
}
return table;
}
#endregion
}
好吧,它必須像以下一樣使用:
var myEntityBulk = new BulkInsert<MyEntity>(
_mYConnectionString,
"MyEntities",
myEntities,
new[] { "ObjectState","NavigationPropertyOne", "NavigationPropertyTwo" }
);
myEntityBulk.Insert();
我希望它有所幫助,我很確定它會...我昨天在幾分鍾內就與它和M實體進行了大量合作。
首先,如果您只是將記錄插入數據庫,請確保是否可以連接到Azure SQL數據庫並執行沒有超時錯誤的操作。
其次,請檢查是否通過使用ObjectContext上的CommandTimeout屬性覆蓋默認超時值,並且可以嘗試為BulkCopyTimeout屬性設置0(表示無限制)。
此外,在批量插入時,請確保它是否達到Azure SQL數據庫的限制,您可以嘗試更改數據庫的服務層和性能級別 。
使用SqlBulkCopy時,依賴於Web服務器和Azure SQL服務器之間的Route-Trip-Time(距離),您需要注意兩個參數:
BatchSize(對我來說,我將批量大小設置為500)
BulkCopyTimeOut:默認為30秒(我設置為60秒)
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection)) { bulkCopy.BatchSize = array.Length; bulkCopy.DestinationTableName = tempTableName; bulkCopy.BulkCopyTimeout = 60;...}
通過這種配置,我從EventStore到我的Projection MicroService獲取20K +事件的整個過程,然后microService更新/將這些20K事件寫入數據庫花了大約15分鍾(取決於事件存儲和MicroService之間的RTT路由行程時間) ,以及Microservice和數據庫之間)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.