相关疑难解决方法(0)

如何将数组传递给SQL Server存储过程

如何将数组传递给SQL Server存储过程?

例如,我有一份员工清单.我想将此列表用作表,并将其与另一个表连接.但是员工列表应该作为参数从C#传递.

c# t-sql sql-server stored-procedures

275
推荐指数
10
解决办法
35万
查看次数

bcp/BULK INSERT与表值参数的性能

我将不得不使用SQL Server的BULK INSERT命令重写一些相当旧的代码,因为架构已经改变,而且我想到也许我应该考虑用TVP切换到存储过程,但我想知道是什么影响它可能有性能.

一些背景信息可能有助于解释我为什么问这个问题:

  • 数据实际上是通过Web服务提供的.Web服务将文本文件写入数据库服务器上的共享文件夹,该文件夹依次执行BULK INSERT.这个过程最初是在SQL Server 2000上实现的,当时除了INSERT在服务器上丢失几百个语句之外别无选择,这实际上是原始进程并且是性能灾难.

  • 将数据批量插入永久登台表,然后合并到更大的表中(之后将其从登台表中删除).

  • 要插入的数据量是"大",但不是"巨大的" - 通常是几百行,在极少数情况下可能是5-10k行.因此,我的直觉是,BULK INSERT作为一个非记录操作不会产生那么大的差异(但当然我不确定,因此问题).

  • 插入实际上是一个更大的流水线批处理过程的一部分,需要连续多次发生; 因此性能至关重要的.

我想BULK INSERT用TVP 取代的原因是:

  • 在NetBIOS上编写文本文件可能已经花费了一些时间,而且从架构的角度来看它非常可怕.

  • 我相信可以(而且应该)消除临时表.它的主要原因是插入的数据需要在插入的同时用于其他几个更新,并且尝试从大量生产表进行更新比使用几乎空的分段更加昂贵表.使用TVP,参数基本上临时表,我可以在主插入之前/之后用它做任何我想做的事情.

  • 我几乎可以废除欺骗检查,清理代码以及与批量插入相关的所有开销.

  • 如果服务器同时获得一些这些事务,我们无需担心登台表或tempdb上的锁争用(我们尽量避免它,但它会发生).

在将任何内容投入生产之前,我显然会对此进行分析,但我认为在我花费所有时间之前首先询问周围可能是一个好主意,看看是否有任何人有关于为此目的使用TVP的任何严厉警告.

那么 - 对于那些对SQL Server 2008足够惬意的人来说,或者至少已经对此进行了调查,那么判决是什么?对于插入,比方说,几百到几千行,经常发生,TVP切割芥末?与批量插入相比,性能是否存在显着差异?


更新:现在问号减少了92%!

(又名:测试结果)

最终的结果是在感觉像36阶段部署过程之后的生产中.两种解决方案都经过了广泛测试

  • 剥离共享文件夹代码并SqlBulkCopy直接使用该类;
  • 使用TVP切换到存储过程.

只是让读者可以得到一个想法是什么确切地进行了测试,以消除任何怀疑这个数据的可靠性,这里是什么这个导入过程更详细的解释实际上做:

  1. 从时间数据序列开始,通常约为20-50个数据点(尽管有时可能会达到几百个);

  2. 做一大堆疯狂的处理,主要是独立于数据库.该过程是并行化的,因此(1)中的大约8-10个序列同时被处理.每个并行过程生成3个附加序列.

  3. 取所有3个序列和原始序列并将它们组合成一批.

  4. 将所有8-10个现已完成的加工任务的批次合并为一个大型超级批次.

  5. 使用BULK INSERT策略(请参阅下一步)或TVP策略(跳至步骤8)导入.

  6. 使用SqlBulkCopy该类将整个超级批处理转储到4个永久临时表中.

  7. 运行存储过程,(a)对其中两个表执行一系列聚合步骤,包括几个JOIN条件,然后(b)MERGE使用聚合和非聚合数据执行6个生产表.(成品)

    要么

  8. 生成DataTable包含要合并的数据的4个对象; 其中3个包含CLR类型,遗憾的是ADO.NET TVP不能正确支持它们,因此必须将它们作为字符串表示形式推入,这会对性能造成一定影响.

  9. 将TVP馈送到存储过程,该过程基本上与(7)进行相同的处理,但是直接与接收的表一起进行.(成品)

结果相当接近,但TVP方法最终平均表现更好,即使数据少量超过1000行. …

performance bulkinsert sql-server-2008 table-valued-parameters

77
推荐指数
3
解决办法
3万
查看次数

如何在最短的时间内插入1000万条记录?

我有一个文件(有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)

c# sql-server import bulkinsert table-valued-parameters

26
推荐指数
2
解决办法
1万
查看次数

表值参数性能的问题

我不知道这是否是我使用它们或Microsoft的实现的问题,但SQL 2008表值参数非常缓慢.

一般来说,如果我需要使用TVP,那是因为我有很多记录 - 目前它们似乎比最少的记录速度慢得多.

我在.Net中调用它们是这样的:

// get the data
DataTable data = GetData();

com.CommandText = "sprocName"

// create the table-value parameter
var tvp = com.Parameters.AddWithValue("data", data);
tvp.SqlDbType = SqlDbType.Structured;

com.ExecuteNonQuery();
Run Code Online (Sandbox Code Playgroud)

我运行探查器来查看原因,实际的SQL语句是这样的:

declare @data table ...

insert into @data ( ... fields ... ) values ( ... values ... )
-- for each row
insert into @data ( ... fields ... ) values ( ... values ... )

sprocName(@data)
Run Code Online (Sandbox Code Playgroud)

尽管如此,这是一个非常缓慢的方法.如果这样做会更快:

insert into @data ( ... fields ... ) 
values ( …
Run Code Online (Sandbox Code Playgroud)

.net sql-server performance sql-server-2008 table-valued-parameters

13
推荐指数
2
解决办法
5208
查看次数

为什么`nvarchar`参数比'text'`SqlCommand`命令的其他类型更快?

概观

这个问题是这个问题的一个更具体的版本:

但我注意到其他数据类型的性能相同(事实上,在我的情况下,我根本没有使用任何bigint类型).

以下是一些其他问题似乎应该涵盖这个问题的答案,但我观察的是他们所指出的相反的问题:

上下文

我有一些C#代码用于将数据插入表中.代码本身是数据驱动的,因为一些其他数据指定了应该插入数据的目标表.所以,我可以在存储过程中使用动态SQL,我选择在我的C#应用​​程序中生成动态SQL.

对于第I行插入,命令文本始终相同,因此在插入任何行之前,我会生成一次.命令文本的格式如下:

INSERT SomeSchema.TargetTable ( Column1, Column2, Column3, ... )
VALUES ( SomeConstant, @p0, @p1, ... );
Run Code Online (Sandbox Code Playgroud)

对于每个插入,我创建一个SqlParameter对象数组.

对于' nvarchar'行为,我只是使用SqlParameter(string parameterName, object value)构造函数方法,而不是显式设置任何其他属性.

对于"简并的行为,我所用的SqlParameter(string parameterName, SqlDbType dbType)构造方法,并且还设定Size,PrecisionScale特性适当.

对于这两个版本的代码,传递给构造函数方法或单独分配给Value属性的值的类型为object.

' nvarchar'版本的代码大约需要1-1.5分钟."退化"或"特定类型"代码需要超过9分钟; 所以慢了6-9倍.

SQL Server Profiler没有透露任何明显的罪魁祸首.特定于类型的代码生成看起来更好的SQL,即动态SQL命令,其参数包含适当的数据类型和类型信息.

假设

我怀疑,因为我传递了一个object类型值作为参数值,ADO.NET …

c# sql-server

5
推荐指数
1
解决办法
425
查看次数

从 C# SQLCLR 存储过程批量插入 SQL 表的最快方法

我有一个 C# SQLCLR 存储过程,其中首先将数据填充到一些字典中并进行计算,然后将输出存储在其他一些字典中。

由于使用了字典,该计算完成得非常快,并且完全证明了我需要使用 CLR 存储过程而不是普通的 SQL 存储过程。

然而,我必须将这些输出字典中的数据保存在 SQL 中的某些表中,这部分花费了很多时间,并且满足了我对整个 SQLCLR 过程更快的需求。

我必须迭代每个输出字典的每个键,然后必须创建插入查询,然后必须按以下方式运行 ExecuteNonQuery: 在此输入图像描述

那么我该如何改进我的这种方法,以便在插入数据时不需要花费时间。我无法使用SqlBulkCopy,因为它不接受进程内上下文连接(即"Context Connection = true;")作为连接字符串。那么还有其他更快的方法可用吗?提前致谢。

c# sql-server import sqlclr sql-server-2008

3
推荐指数
1
解决办法
5155
查看次数