针对Sqlserver大数据量插入速度慢或丢失数据的解决方法

我的设备上每秒将2000条数据插入数据库,2个设备总共4000条,当在程序里面直接用insert语句插入时,两个设备同时插入大概总共能插入约2800条左右,数据丢失约1200条左右,测试了很多方法,整理出了两种效果比较明显的解决办法:

方法一:使用Sql Server函数:

1.将数据组合成字串,使用函数将数据插入内存表,后将内存表数据复制到要插入的表。

2.组合成的字符换格式:'111|222|333|456,7894,7458|0|1|2014-01-01 12:15:16;1111|2222|3333|456,7894,7458|0|1|2014-01-01 12:15:16',每行数据中间用“;”隔开,每个字段之间用“|”隔开。

3.编写函数:

CREATE FUNCTION [dbo].[fun_funcname](@str VARCHAR(max),@splitchar CHAR(1),@splitchar2 CHAR(1)) --定义返回表 RETURNS @t TABLE(MaxValue float,Phase int,SlopeValue float,Data varchar(600),Alarm int,AlmLev int,GpsTime datetime,UpdateTime datetime) AS /* author:hejun li create date:2014-06-09 */ BEGIN DECLARE @substr VARCHAR(max),@substr2 VARCHAR(max) --申明单个接收值 declare @MaxValue float,@Phase int,@SlopeValue float,@Data varchar(8000),@Alarm int,@AlmLev int,@GpsTime datetime SET @substr=@str DECLARE @i INT,@j INT,@ii INT,@jj INT,@ijj1 int,@ijj2 int,@m int,@mm int SET @j=LEN(REPLACE(@str,@splitchar,REPLICATE(@splitchar,2)))-LEN(@str)--获取分割符个数 IF @j=0 BEGIN --INSERT INTO @t VALUES (@substr,1) --没有分割符则插入整个字串 set @substr2=@substr; set @ii=0 SET @jj=LEN(REPLACE(@substr2,@splitchar2,REPLICATE(@splitchar2,2)))-LEN(@substr2)--获取分割符个数 WHILE @ii<=@jj BEGIN if(@ii<@jj) begin SET @mm=CHARINDEX(@splitchar2,@substr2)-1 --获取分割符的前一位置 if(@ii=0) set @MaxValue=cast(LEFT(@substr2,@mm) as float) else if(@ii=1) set @Phase=cast(LEFT(@substr2,@mm) as int) else if(@ii=2) set @SlopeValue=cast(LEFT(@substr2,@mm) as float) else if(@ii=3) set @Data=cast(LEFT(@substr2,@mm) as varchar) else if(@ii=4) set @Alarm=cast(LEFT(@substr2,@mm) as int) else if(@ii=5) set @AlmLev=cast(LEFT(@substr2,@mm) as int) else if(@ii=6) INSERT INTO @t VALUES(@MaxValue,@Phase,@SlopeValue,''+@Data+'',@Alarm,@AlmLev,cast(@substr2 as datetime),GETDATE()) SET @substr2=RIGHT(@substr2,LEN(@substr2)-(@mm+1)) --去除已获取的分割串,得到还需要继续分割的字符串 end else BEGIN --当循环到最后一个值时将数据插入表 INSERT INTO @t VALUES(@MaxValue,@Phase,@SlopeValue,''+@Data+'',@Alarm,@AlmLev,cast(@substr2 as datetime),GETDATE()) END --END SET @ii=@ii+1 END END ELSE BEGIN SET @i=0 WHILE @i<=@j BEGIN IF(@i<@j) BEGIN SET @m=CHARINDEX(@splitchar,@substr)-1 --获取分割符的前一位置 --INSERT INTO @t VALUES(LEFT(@substr,@m),@i+1) -----二次循环开始 --1.线获取要二次截取的字串 set @substr2=(LEFT(@substr,@m)); --2.初始化二次截取的起始位置 set @ii=0 --3.获取分隔符个数 SET @jj=LEN(REPLACE(@substr2,@splitchar2,REPLICATE(@splitchar2,2)))-LEN(@substr2)--获取分割符个数 WHILE @ii<=@jj BEGIN if(@ii<@jj) begin SET @mm=CHARINDEX(@splitchar2,@substr2)-1 --获取分割符的前一位置 if(@ii=0) set @MaxValue=cast(LEFT(@substr2,@mm) as float) else if(@ii=1) set @Phase=cast(LEFT(@substr2,@mm) as int) else if(@ii=2) set @SlopeValue=cast(LEFT(@substr2,@mm) as float) else if(@ii=3) set @Data=cast(LEFT(@substr2,@mm) as varchar) else if(@ii=4) set @Alarm=cast(LEFT(@substr2,@mm) as int) else if(@ii=5) set @AlmLev=cast(LEFT(@substr2,@mm) as int) else if(@ii=6) INSERT INTO @t VALUES(@MaxValue,@Phase,@SlopeValue,''+@Data+'',@Alarm,@AlmLev,cast(@substr2 as datetime),GETDATE()) SET @substr2=RIGHT(@substr2,LEN(@substr2)-(@mm+1)) --去除已获取的分割串,得到还需要继续分割的字符串 end else BEGIN --当循环到最后一个值时将数据插入表 INSERT INTO @t VALUES(@MaxValue,@Phase,@SlopeValue,''+@Data+'',@Alarm,@AlmLev,cast(@substr2 as datetime),GETDATE()) END --END SET @ii=@ii+1 END -----二次循环结束 SET @substr=RIGHT(@substr,LEN(@substr)-(@m+1)) --去除已获取的分割串,得到还需要继续分割的字符串 END ELSE BEGIN --INSERT INTO @t VALUES(@substr,@i+1)--对最后一个被分割的串进行单独处理 -----二次循环开始 --1.线获取要二次截取的字串 set @substr2=@substr; --2.初始化二次截取的起始位置 set @ii=0 --3.获取分隔符个数 SET @jj=LEN(REPLACE(@substr2,@splitchar2,REPLICATE(@splitchar2,2)))-LEN(@substr2)--获取分割符个数 WHILE @ii<=@jj BEGIN if(@ii<@jj) begin SET @mm=CHARINDEX(@splitchar2,@substr2)-1 --获取分割符的前一位置 if(@ii=0) set @MaxValue=cast(LEFT(@substr2,@mm) as float) else if(@ii=1) set @Phase=cast(LEFT(@substr2,@mm) as int) else if(@ii=2) set @SlopeValue=cast(LEFT(@substr2,@mm) as float) else if(@ii=3) set @Data=cast(LEFT(@substr2,@mm) as varchar) else if(@ii=4) set @Alarm=cast(LEFT(@substr2,@mm) as int) else if(@ii=5) set @AlmLev=cast(LEFT(@substr2,@mm) as int) else if(@ii=6) INSERT INTO @t VALUES(@MaxValue,@Phase,@SlopeValue,''+@Data+'',@Alarm,@AlmLev,cast(@substr2 as datetime),GETDATE()) SET @substr2=RIGHT(@substr2,LEN(@substr2)-(@mm+1)) --去除已获取的分割串,得到还需要继续分割的字符串 end else BEGIN --当循环到最后一个值时将数据插入表 INSERT INTO @t VALUES(@MaxValue,@Phase,@SlopeValue,''+@Data+'',@Alarm,@AlmLev,cast(@substr2 as datetime),GETDATE()) END SET @ii=@ii+1 END -----二次循环结束 END SET @i=@i+1 END END RETURN END

4.调用函数语句:

insert into [mytable] select * from [dbo].[fun_funcname]('111|222|333|456,7894,7458|0|1|2014-01-01 12:15:16;1111|2222|3333|456,7894,7458|0|1|2014-01-01 12:15:16',';','|');

5.结果展示:

select * from [mytable] ;

方法二:使用BULK INSERT

大数据量插入第一种操作,使用Bulk将文件数据插入数据库

Sql代码

创建数据库

CREATE DATABASE [db_mgr] GO

创建测试表

USE db_mgr CREATE TABLE dbo.T_Student( F_ID [int] IDENTITY(1,1) NOT NULL, F_Code varchar(10) , F_Name varchar(100) , F_Memo nvarchar(500) , F_Memo2 ntext , PRIMARY KEY (F_ID) ) GO

填充测试数据

Insert Into T_Student(F_Code, F_Name, F_Memo, F_Memo2) select 'code001', 'name001', 'memo001', '备注' union all select 'code002', 'name002', 'memo002', '备注' union all select 'code003', 'name003', 'memo003', '备注' union all select 'code004', 'name004', 'memo004', '备注' union all select 'code005', 'name005', 'memo005', '备注' union all select 'code006', 'name006', 'memo006', '备注'

开启xp_cmdshell存储过程(开启后有安全隐患)

EXEC sp_configure 'show advanced options', 1; RECONFIGURE;EXEC sp_configure 'xp_cmdshell', 1; EXEC sp_configure 'show advanced options', 0; RECONFIGURE;

使用bcp导出格式文件:

EXEC master..xp_cmdshell 'BCP db_mgr.dbo.T_Student format nul -f C:/student_fmt.xml -x -c -T'

使用bcp导出数据文件:

EXEC master..xp_cmdshell 'BCP db_mgr.dbo.T_Student out C:/student.data -f C:/student_fmt.xml -T'

将表中数据清空

truncate table db_mgr.dbo.T_Student

使用Bulk Insert语句批量导入数据文件:

BULK INSERT db_mgr.dbo.T_Student FROM 'C:/student.data' WITH ( FORMATFILE = 'C:/student_fmt.xml' )

使用OPENROWSET(BULK)的例子:

T_Student表必须已存在

INSERT INTO db_mgr.dbo.T_Student(F_Code, F_Name) SELECT F_Code, F_Name FROM OPENROWSET(BULK N'C:/student.data', FORMATFILE=N'C:/student_fmt.xml') AS new_table_name

使用OPENROWSET(BULK)的例子:

tt表可以不存在

SELECT F_Code, F_Name INTO db_mgr.dbo.tt FROM OPENROWSET(BULK N'C:/student.data', FORMATFILE=N'C:/student_fmt.xml') AS new_table_name

时间: 2024-09-21 06:05:47

针对Sqlserver大数据量插入速度慢或丢失数据的解决方法的相关文章

dataset-sql server 存储过程在执行批量导入的时候由于导入的数据量太大报错,有没有优化的方法 ?

问题描述 sql server 存储过程在执行批量导入的时候由于导入的数据量太大报错,有没有优化的方法 ? @dataset xml AS BEGIN SET NOCOUNT ON; begin tran insert into student select src.a.value('./编号[1]','varchar(10)') as Id , src.a.value('./姓名[1]','varchar(10)') as Name , src.a.value('./学号[1]','varch

SqlBulkCopy批量插入数据时,不执行触发器和约束的解决方法

原文:SqlBulkCopy批量插入数据时,不执行触发器和约束的解决方法 在new SqlBulkCopy对象的时候,设置一下SqlBulkCopyOptions选项即可,按位或运算 SqlBulkCopyOptions.FireTriggers | SqlBulkCopyOptions.CheckConstraints using (SqlBulkCopy bulkCopy = new SqlBulkCopy(GlobalString.ConnectionString, SqlBulkCopy

导致U盘插入后无盘符显示的解决方法

  导致U盘插入后无盘符显示的解决方法           如今U盘真是随处可见,现在不仅仅是从事IT业的人士才会用到的存储工具基本上都会买一个存储数据以及文件. 当然u盘用的多了出现的问题也会相对而言比较多. 那么今天XP系统大全跟大家分享下针对为什么U盘插入后出现了无盘符显示的原因分析和解释. XP系统在安装sp2以后插入U盘,能正确识别,但是资源管理器里却没有盘符,而其他USB设备(如:鼠标)则没有故障,更换U盘测试,故障相同,主要的原因是设置的一个网络硬盘的盘符与分配给U盘的盘符相同,解

Mysql大指量插入数据时SQL语句的优化

1) 对于Myisam类型的表,可以通过以下方式快速的导入大量的数据.       ALTER TABLE tblname DISABLE KEYS;     loading the data     ALTER TABLE tblname ENABLE KEYS; 这两个命令用来打开或者关闭Myisam表非唯一索引的更新.在导入大量的数据到一个非空的Myisam表时,通过设置这两个命令,可以提高导入的效率.对于导入大量数据到一个空的Myisam表,默认就是先导入数据然后才创建索引的,所以不用进

大数据量数据库如何简单备份迁移数据

今天真汗颜啊....由于我的一不小心,我把几百万条数据给删了,囧.客户的几年重要数据就这样没了,我当时愁的,还好后来找回来了. 对于大数据的操作,大家一定要慎重操作. 在SQLServer2005中,想从一个数据库服务器迁移一个数据表的数据到另一数据库服务器的表中,大家一般会怎么做呢? 我先来说说我今天的做法:(因为自己的笔记本上没有装软件,不能截图给大家看了,大家可以自己动手操作下) 刚开始我利用一种方法,很笨且不安全的,大家引以为戒. 老大交给我任务了,我一想那么多数据,总不能一条一条手工插

.net 通过OLEDB获取excel数据,插入oracle之后,中文成“???”怎么解决啊?

问题描述 如题,我是获取的excel数据,插入到oracle的,结果中文变成了问号,如果是表单数据直接插入oralce的话就没问题,什么情况? 解决方案 解决方案二:对有中文的字段用gb2312编码解决方案三:那说明读EXCEL的时候读出来的就是乱码.先好好断点测一下到底哪里出的问题.解决方案四:引用2楼Z65443344的回复: 那说明读EXCEL的时候读出来的就是乱码.先好好断点测一下到底哪里出的问题. 是在没办法了,改了一下注册表,没抱任何希望滴重启了一下电脑,试了下,尼玛啊,竟然好了!!

Wi-Fi速度慢的原因及常见解决方法

第一套801.11ac芯片即将来到,但802.11n可能还会存在很多年,无论是企业还是家庭使用.然而,n标准承诺的300Mbps(兆比特每秒)很少实现,并且它被证明给50/100Mbps宽带连接.1080p视频流.大规模备份等带来巨大瓶颈问题.在企业方面,一些琐碎的工作(例如远程桌面或实时协作)都受到糟糕的Wi-Fi连接的影响. 在我们的测试中,我们经常会看到这样的结果:通过802.11n连接,只相隔几米(中间只有一面墙)的设备速度会下降到只有2-15Mbps,这里就是你会遇到的问题: 1. 0

php中导出数据到excel时数字变为科学计数的解决方法_php技巧

在数据导出到excel时数字格式不对,一般分为以下两种情况. 1.excel单元格设置长度不够 解决方法: 复制代码 代码如下: //在excel.php文件中 $objActSheet = $objPHPExcel->getActiveSheet(); // 设置 栏目名称 $objActSheet->setCellValue("b1", "卡号"); // 设置列的宽度 $objActSheet->getColumnDimension('b')

picturebox 控件加载大图片的时候。显示红叉,有解决方法吗?

问题描述 我用DrawImage画了一个大约100mb左右大小的图片.然后加载的picturebox上显示.但是显示了一个巨大的红叉,但我用picturebox.Image.Save能正确的保存,保存的图片其它软件都能打开.请问是什么原因啊.就是picturebox.Image显示不了啊!有什么解决方法没有啊! 解决方案 解决方案二:检查一下路径.格式以及加载情况.这么大的文件,你是用来做什么的?为什么不尝试用缩略图来做展示呢?解决方案三:引用1楼fei2yun的回复: 检查一下路径.格式以及加