我正在寻找通过c#加载批量数据的最快方法。我有这个脚本可以完成这项工作,但速度很慢。我读过SqlBulkCopy最快的证词 1000记录2.5秒。文件包含近5000条记录到250k的任何地方 有什么东西可以减缓它?
表格默认:
CREATE TABLE [dbo].[tempDispositions](
[QuotaGroup] [varchar](100) NULL,
[Country] [varchar](50) NULL,
[ServiceGroup] [varchar](50) NULL,
[Language] [varchar](50) NULL,
[ContactChannel] [varchar](10) NULL,
[TrackingID] [varchar](20) NULL,
[CaseClosedDate] [varchar](25) NULL,
[MSFTRep] [varchar](50) NULL,
[CustEmail] [varchar](100) NULL,
[CustPhone] [varchar](100) NULL,
[CustomerName] [nvarchar](100) NULL,
[ProductFamily] [varchar](35) NULL,
[ProductSubType] [varchar](255) NULL,
[CandidateReceivedDate] [varchar](25) NULL,
[SurveyMode] [varchar](1) NULL,
[SurveyWaveStartDate] [varchar](25) NULL,
[SurveyInvitationDate] [varchar](25) NULL,
[SurveyReminderDate] [varchar](25) NULL,
[SurveyCompleteDate] [varchar](25) NULL,
[OptOutDate] [varchar](25) NULL,
[SurveyWaveEndDate] [varchar](25) NULL,
[DispositionCode] [varchar](5) NULL,
[SurveyName] [varchar](20) NULL,
[SurveyVendor] [varchar](20) NULL,
[BusinessUnitName] [varchar](25) NULL,
[UploadId] [int] NULL,
[LineNumber] [int] NULL,
[BusinessUnitSubgroup] [varchar](25) NULL,
[FileDate] [datetime] NULL
) ON [PRIMARY]
这是代码
private void BulkLoadContent(DataTable dt)
{
OnMessage("Bulk loading records to temp table");
OnSubMessage("Bulk Load Started");
using (SqlBulkCopy bcp = new SqlBulkCopy(conn))
{
bcp.DestinationTableName = "dbo.tempDispositions";
bcp.BulkCopyTimeout = 0;
foreach (DataColumn dc in dt.Columns)
{
bcp.ColumnMappings.Add(dc.ColumnName, dc.ColumnName);
}
bcp.NotifyAfter = 2000;
bcp.SqlRowsCopied += new SqlRowsCopiedEventHandler(bcp_SqlRowsCopied);
bcp.WriteToServer(dt);
bcp.Close();
}
}
答案 0 :(得分:7)
您对该表有任何索引,触发器或约束吗?
这将导致插入速度减慢 - 尤其是聚簇索引会受到影响。 在爆破您正在进行的数据量时,最好先删除索引,然后再重新应用它们。
关于它的好帖子在这里: What's the fastest way to bulk insert a lot of data in SQL Server (C# client)
答案 1 :(得分:3)
如果您有大量数据,将batchsize设置为相当大的数字可能会有所帮助:
bcp.BatchSize = 10000;
答案 2 :(得分:1)
可以减慢批量复制的事情: - 表上的全文本索引 - 插入时的触发器 -Foreign-Key约束
答案 3 :(得分:1)
我注意到,尝试刷新大型数据集的速度最初要快得多,但随着时间的推移会大幅减慢。我发现使用缓冲方法适度增加了性能,在同一连接下一次只为几千条记录提供批量复制。它似乎可以保持每批次的交易时间随着时间的推移而下降,这会(随着时间的推移)提高性能。在我的解决方案中,我已经注意到,在此方法将相同类型的大约7,500,000条记录保存到同一个数据库所需的时间内,未缓冲的相同方法将节省大约5,000,000条记录。 希望这有助于某人。
public void flush_DataTable(DataTable dt, string tableName)//my incoming DTs have a million or so each and slow down over time to nothing. This helps.
{ int bufferSize = 10000;
int bufferHigh = bufferSize;
int lowBuffer = 0;
if (dt.Rows.Count >= bufferSize)
{ using (SqlConnection conn = getConn())
{ conn.Open();
while (bufferHigh < dt.Rows.Count)
{
using (SqlBulkCopy s = new SqlBulkCopy(conn))
{ s.BulkCopyTimeout = 900;
s.DestinationTableName = tableName;
s.BatchSize = bufferSize;
s.EnableStreaming = true;
foreach (var column in dt.Columns)
s.ColumnMappings.Add(column.ToString(), column.ToString());
DataTable bufferedTable = dt.Clone();
for (int bu = lowBuffer; bu < bufferHigh; bu++)
{
bufferedTable.ImportRow(dt.Rows[bu]);
}
s.WriteToServer(bufferedTable);
if (bufferHigh == dt.Rows.Count)
{
break;
}
lowBuffer = bufferHigh;
bufferHigh += bufferSize;
if (bufferHigh > dt.Rows.Count)
{
bufferHigh = dt.Rows.Count;
}
}
}
conn.Close();
}
}
else
{
flushDataTable(dt, tableName);//perofrm a non-buffered flush (could just as easily flush the buffer here bu I already had the other method
}
}
答案 4 :(得分:0)
我建议她How to implement IDataReader?的IDataReader实现可能对您有所帮助。我在SqlBulkCopy中使用它如下:
using (MyFileDataReader reader = new MyFileDataReader(@"C:\myfile.txt"))
{
SqlBulkCopy bulkCopy = new SqlBulkCopy(connection);
bulkCopy.DestinationTableName = "[my_table]";
bulkCopy.BatchSize = 10000;
bulkCopy.WriteToServer(reader);
bulkCopy.Close();
}
答案 5 :(得分:0)
设置BatchSize或NotifyAfter都会导致速度变慢。
如果您有数据读取器,则可以将其与行计数数据读取器包装起来以获取进度。
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection))
{
bulkCopy.EnableStreaming = true;
bulkCopy.BulkCopyTimeout = 0;
using (var reader = new MyRowCountDataReader(dataReader))
{
reader.NotifyAfter = 1000;
reader.RowRead += (sender, args) => { ... };
bulkCopy.WriteToServer(reader);
}
}