我有一个项目涉及将设备中的数据直接记录到sql表中。
在写入sql server(2008顺便说一句)之前,我在代码中进行的处理很少
通常我使用sqlhelper类的ExecuteNonQuery方法并传入一个存储的proc名称和SP期望的参数列表。
这非常方便,但我需要一种更快的方法。
感谢。
答案 0 :(得分:45)
使用INSERT语句或甚至存储过程的ExecuteNonQuery将使您在Express上每秒进行数千次插入。 4000-5000 /秒很容易实现,我知道这是事实。
通常会减慢个别更新的速度是日志刷新的等待时间,您需要考虑到这一点。最简单的解决方案是简单地批量提交。例如。每1000次插入或每秒提交一次。这将填满日志页面,并将分摊事务中所有插入的日志刷新等待的成本。
使用批量提交,您可能会遇到磁盘日志写入性能的瓶颈,除了更改硬件(在日志上进行raid 0条带化)之外,没有什么可以做的。
如果你遇到了早期的瓶颈(不太可能),那么你可以查看批处理语句,即。发送一个包含多个插入的T-SQL批处理。但这很少有回报。
当然,您需要将写入的大小减小到最小,这意味着将表的宽度减少到最低需要的列,消除非聚簇索引,消除不需要的约束。如果可能,请使用堆而不是聚簇索引,因为堆插入明显快于聚簇索引。
几乎不需要使用快速插入接口(即SqlBulkCopy)。在批量提交中使用普通的INSERTS和ExecuteNoQuery,您将耗尽驱动器顺序写入吞吐量,这比部署批量插入的速度要快得多。快速SAN连接的机器上需要批量插入,你提到Express,所以可能不是这样。那里有一种相反的看法,但仅仅是因为人们没有意识到批量插入给了他们批量提交,并且它的批量提交加速了,而不是批量插入。
与任何性能测试一样,确保消除随机性,并且预分配数据库和日志,您不希望在测试测量期间或生产期间点击db或log growth事件,是太业余了。
答案 1 :(得分:4)
批量插入将是最快的,因为它是最少记录的
.NET也有SqlBulkCopy Class
答案 2 :(得分:2)
这通常是通过BULK INSERT完成的。基本上,您准备一个文件,然后发出BULK INSERT
语句,SQL Server使用快速方法将文件中的所有数据复制到表中。
它确实有一些限制(例如,如果您有可能存在的行要更新,则无法执行“更新或插入”类型的行为),但如果您可以解决这些问题,那么您不太可能找到更快的东西。
答案 3 :(得分:2)
可以减慢插入的事情包括同一个表上的索引和读取或更新(锁)。您可以通过避免这两种情况并将单个事务插入到没有索引或其他活动的单独保留表中来加速像您这样的情况。然后将保持台分批到主表中不那么频繁。
答案 4 :(得分:2)
这是使用表变量插入大量记录的好方法......
...但最好一次将其限制为1000条记录,因为表变量是“在内存中”
在这个例子中,我将2个记录插入到一个包含3个字段的表中 - CustID,名字,姓氏
--first create an In-Memory table variable with same structure
--you could also use a temporary table, but it would be slower
declare @MyTblVar table (CustID int, FName nvarchar(50), LName nvarchar(50))
insert into @MyTblVar values (100,'Joe','Bloggs')
insert into @MyTblVar values (101,'Mary','Smith')
Insert into MyCustomerTable
Select * from @MyTblVar
答案 5 :(得分:1)
如果您的意思是来自.NET,请使用SqlBulkCopy
答案 6 :(得分:1)
它只能像你的SP一样快。确保表已正确编入索引,如果您有聚簇索引,请确保它具有一个狭窄,唯一,增加的键。确保剩余的索引和约束(如果有的话)没有很多开销。
您不应该在ADO.NET层中看到太多开销(我不一定会在SQLCommand之上使用任何其他.NET库)。您可以使用ADO.NET Async方法将多个调用排队到存储过程,而不会阻塞应用程序中的单个线程(这可能会释放比其他任何东西更多的吞吐量 - 就像将多台机器插入数据库一样)。
除此之外,你真的需要告诉我们更多关于你的要求。