我有一个文件(有1000万条记录),如下所示:
line1
line2
line3
line4
.......
......
10 million lines
Run Code Online (Sandbox Code Playgroud)
所以基本上我想在数据库中插入1000万条记录.所以我读了文件并将其上传到SQL Server.
C#代码
System.IO.StreamReader file =
new System.IO.StreamReader(@"c:\test.txt");
while((line = file.ReadLine()) != null)
{
// insertion code goes here
//DAL.ExecuteSql("insert into table1 values("+line+")");
}
file.Close();
Run Code Online (Sandbox Code Playgroud)
但插入需要很长时间.如何使用C#在尽可能短的时间内插入1000万条记录?
更新1:
批量插入:
BULK INSERT DBNAME.dbo.DATAs
FROM 'F:\dt10000000\dt10000000.txt'
WITH
(
ROWTERMINATOR =' \n'
);
Run Code Online (Sandbox Code Playgroud)
我的表如下:
DATAs
(
DatasField VARCHAR(MAX)
)
Run Code Online (Sandbox Code Playgroud)
但我得到以下错误:
Msg 4866,Level 16,State 1,Line 1
批量加载失败.第1行第1列的数据文件中的列太长.验证是否正确指定了字段终止符和行终止符.消息7399,级别16,状态1,行1
链接服务器"(null)"的OLE DB提供程序"BULK"报告错误.提供商未提供有关错误的任何信息.消息7330,级别16,状态2,行1
无法从OLE DB提供程序"BULK"获取链接服务器"(null)"的行.
下面的代码工作:
BULK INSERT DBNAME.dbo.DATAs
FROM 'F:\dt10000000\dt10000000.txt'
WITH
(
FIELDTERMINATOR = '\t',
ROWTERMINATOR …Run Code Online (Sandbox Code Playgroud) 我目前的项目包括3个标准层:数据,业务和演示.我想使用数据实体来满足我的所有数据访问需求.应用程序的部分功能是需要将平面文件中的所有数据复制到数据库中.该文件不是很大,所以我可以使用SqlBulkCopy.我在.NET中找到了几篇关于SqlBulkCopy类用法的文章.但是,所有文章都使用DataTable来来回移动数据.
有没有办法将数据实体与SqlBulkCopy一起使用,还是必须使用DataTables?
我正在编写一个存储过程来将行插入表中.问题是,在某些操作中,我们可能希望插入超过100万行,并且我们希望使其快速.另一件事是,在其中一个专栏中,它是Nvarchar(MAX).我们可能希望在此列中放置平均1000个字符.
首先,我写了一个prc来逐行插入.然后我生成一些随机数据用于插入,NVARCHAR(MAX)列为1000个字符的字符串.然后使用循环调用prc来插入行.如果我使用SQL服务器登录要插入的数据库服务器,则perf非常糟糕,需要48分钟.如果我使用C#连接到我桌面上的服务器(这是我们通常想要做的),则需要大约90分钟.
然后,我更改了prc以获取表类型参数作为输入.我以某种方式准备了行并将它们放在表类型参数中并通过以下命令执行插入:
INSERT INTO tableA SELECT * from @tableTypeParameterB
Run Code Online (Sandbox Code Playgroud)
我尝试批量大小为1000行和3000行(在@tableTypeParameterB中放入1000-3000行以插入一次).表现仍然不好.如果我在SQL服务器中运行它需要大约3分钟来插入100万行,如果我使用C#程序从我的桌面连接则需要大约10分钟.
它tableA有一个包含2列的聚簇索引.
我的目标是尽可能快地插入(我的想法目标是在1分钟内).有没有办法优化它?
只是一个更新:
我尝试了下面的一些人建议的批量复制插入.我尝试使用SQLBULKCOPY一次插入1000行和10000行.插入100万行的性能仍然是10分钟(每行有一个1000字符的列).没有性能提升.还有其他建议吗?
基于评论的更新需要.
数据实际上来自UI.用户将更改使用UI以批量选择,我们说,一百万行,并将一列从旧值更改为新值.此操作将在单独的过程中完成.但是,我们需要做的是使中间层服务从UI获取旧值和新值并将其插入表中.旧值和新值最多可包含4000个字符,平均值为1000个字符.我认为长字符串旧/新值会降低速度,因为当我将测试数据旧值/新值更改为20-50个字符并且插入非常快时无论使用SQLBulkCopy还是表类型变量
我需要有效地从Ado.Net向SQl Server 2008提交成千上万的数字和日期.在SQL 2008之前的日子里,我将这些数字打包在图像中,这非常快.Erland Sommarskog非常友好地将我的一些代码包含在SQL Server 2005的文章Arrays and Lists中
因为现在我们可以使用TVP,我尝试了它们.在客户端,我运行这个:
dataTable = new DataTable();
dataTable.Columns.Add("Date", typeof(DateTime));
dataTable.Columns.Add("Price", typeof(decimal));
dataTable.Rows.Add(new object[] { someDate, somePrice });
command.CommandText = "Writers.SavePrices";
command.CommandType = CommandType.StoredProcedure;
var param = command.Parameters.AddWithValue("@Prices", dataTable);
param.SqlDbType = SqlDbType.Structured;
Run Code Online (Sandbox Code Playgroud)
这段代码有效,但我认为它没有效率.我启动了Profiler,我立即看到Ado.Net发出以下效率极低的SQL被发送到服务器:
DECLARE @Prices TABLE(...)
INSERT INTO @Prices(...)VALUES(...)
EXEC Writers.SavePrices @Prices=@Prices
Run Code Online (Sandbox Code Playgroud)
结果,在发送,解析和编译时浪费了服务器上的大量网络带宽和CPU.有没有更有效的方法来使用Ado.Net的TVP?
我有mvc应用程序.在行动中我有Dictionary<string,int>.的Key是ID和Value是sortOrderNumber.我想创建存储过程,将获取密钥(id)在数据库中查找此记录并从Dictionary中保存orderNumber列value.我想一次调用存储过程并将数据传递给它,而不是多次调用更新数据.
你有什么想法吗?谢谢!
sql-server ×4
c# ×3
bulkinsert ×2
import ×2
sqlbulkcopy ×2
.net ×1
ado.net ×1
asp.net-mvc ×1
sql ×1
t-sql ×1