Sql server 大数据量插入速度慢或丢失数据解决办法

问题描述:我的设备每秒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 @[email protected]
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 @[email protected];
      set @ii=0
      SET @jj=LEN(REPLACE(@substr2,@splitchar2,REPLICATE(@splitchar2,2)))-LEN(@substr2)--获取分割符个数
          WHILE  @ii<[email protected]
				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,''[email protected]+'',@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,''[email protected]+'',@Alarm,@AlmLev,cast(@substr2 as datetime),GETDATE())

						END
				--END
				SET @[email protected]+1
			END
    END
ELSE
BEGIN
 SET @i=0
 WHILE @i<[email protected]
 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<[email protected]
        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,''[email protected]+'',@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,''[email protected]+'',@Alarm,@AlmLev,cast(@substr2 as datetime),GETDATE())

				END
        --END
        SET @[email protected]+1
    END
    -----二次循环结束
    SET @substr=RIGHT(@substr,LEN(@substr)-(@m+1)) --去除已获取的分割串,得到还需要继续分割的字符串
   END
  ELSE
   BEGIN
    --INSERT INTO @t VALUES(@substr,@i+1)--对最后一个被分割的串进行单独处理
    -----二次循环开始
    --1.线获取要二次截取的字串
    set @[email protected];
    --2.初始化二次截取的起始位置
    set @ii=0
    --3.获取分隔符个数
    SET @jj=LEN(REPLACE(@substr2,@splitchar2,REPLICATE(@splitchar2,2)))-LEN(@substr2)--获取分割符个数
    WHILE  @ii<[email protected]
        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,''[email protected]+'',@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,''[email protected]+'',@Alarm,@AlmLev,cast(@substr2 as datetime),GETDATE())

				END
        SET @[email protected]+1
    END
    -----二次循环结束
   END
 SET @[email protected]+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 

Sql server 大数据量插入速度慢或丢失数据解决办法

时间: 2024-10-11 02:31:38

Sql server 大数据量插入速度慢或丢失数据解决办法的相关文章

Win 2008 R2安装SQL Server 2008“性能计数器注册表配置单元一致性”失败的解决办法

Win 2008 R2安装SQL Server 2008"性能计数器注册表配置单元一致性"失败的解决办法(2011-02-23 19:37:32) 转载▼   今天在惠普服务器上安装数据库2008时,在进行数据库安装检测时总是有一点通不过,提示"性能计数器注册表配置单元一致性失败".以前在其他的服务器上安装都没有碰到过这个问题.开始以为系统没有装好,后面重装了还是一样的.但同一张系统盘在IBM等其他服务器安装系统后,再安装数据库没有出现此问题,很是令人费解.后来在网

PowerDesigner16 生成的备注脚本,在sql server 2008 中报“对象名 &#39;sysproperties&#39; 无效”的错误的解决办法

主要是在建模时我们对表.列增加了些说明注释,而Sql2005之后系统表sysproperties已废弃删除而改用sys.extended_properties所致. 1.修改Table TableComment 部分 菜单Database -> Edit Current DBMS 窗体 General 选项卡 下 Script -> Objects -> Table –> TableComment 在开头部分替换如下: [if exists (select 1           

SSRS (SQL Server Report Service) 在IE9, IE10下显示不全的解决办法

在做项目的过程中遇到SSRS与IE9, IE10不兼容的情况,具体表现为报表页面在IE9 和 IE10下面只显示三分之一,靠左显示,下方有滚动条,右三分之二为空白.查看源代码后发现,上面一个<tr>里只有一个<td>,并colspan=3, 下面报表内容区域的<tr>有三个<td>但前两个是hidden的.最初是想把表格结构调整下,去掉前面hidden的两个<td>,后来发现太麻烦不说,还改变了微软原来的表单内容.就在网上搜索解决方案,微软自己说

SQL Server子查询填充DataSet时报500内部错误的解决办法

运行环境为Visual Studio 2010,数据库为SQL Server 2008. 执行下面SQL语句 SELECT SubsiteId, SubsiteTitle, count(CollectionID) CollectionNumber,count(LName) PlantNumber FROM (SELECT DISTINCT SubsiteId, SubsiteTitle, CollectionID, LName, CName FROM Cumplag_Garden_Plants

SQL SERVER 2012数据库:开启防火墙导致外部无法连接数据库解决办法

将以下代码存为OpenSqlServerPort.bat文件: netsh advfirewall firewall add rule name="Open Port 80" dir=in action=allow protocol=TCP localport=80 @echo =========  SQL Server Ports  =================== @echo Enabling SQLServer default instance port 1433 nets

C# &amp; SQL Server大数据量插入方式对比

以下内容大部分来自: http://blog.csdn.net/tjvictor/article/details/4360030 部分内容出自互联网,实验结果为亲测. 最近自己开发一个向数据库中插入大量历史数据的函数库,需要解决一个大数据量插入的效率问题.不用分析,我知道如果采取逐条数据插入的方式,那么效率肯定很低,光是那么多循环就知道很慢了.于是乎,我找到了上篇博客,知道了BulkCopy和TVPs方式.为了更好的了解其效率,我自己动手亲测了一下效果,测试的数据库位于本机. (1)方式1:循环

SQL Server 大数据搬迁之文件组备份还原实战

原文:SQL Server 大数据搬迁之文件组备份还原实战 一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 解决方案(Solution) 搬迁步骤(Procedure) 搬迁脚本(SQL Codes) 注意事项(Attention) 疑问(Questions) 参考文献(References) 二.背景(Contexts) 有一个数据库大概在700G左右,需要从服务器A搬迁到服务器B,两台服务器网络传输速度可以达到8MB/s,怎么做才能更

SQL Server 2012中快速插入批量数据的示例及疑惑

SQL Server 2008中SQL应用系列--目录索引 今天在做一个案例演示时,在SQL Server 2012中使用Insert语句插入1万条数据,结果遇到了一个奇怪的现象,现将过程分享出来,以供有兴趣的同学参考. 附:我的测试环境为:SQL Server 2012,命名实例 Microsoft SQL Server 2012 - 11.0.2100.60 (Intel X86) Feb 10 2012 19:13:17 Copyright (c) Microsoft Corporatio

SQL SERVER 使用BULK Insert将txt文件中的数据批量插入表中(1)

1/首先建立数据表 CREATE TABLE BasicMsg( RecvTime FLOAT NOT NULL , --接收时间,不存在时间相同的数据 AA INT NOT NULL, --24位地址码 . FlightID Varchar(10) NULL, --航班号) 2/ 建立存储过程 USE DF17DataProIF EXISTS (SELECT * FROM SYS.PROCEDURES WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[BulkDataP