SqlServer批量复制(bcp)[C#SqlBulkCopy]性能极低问题

  • 背景

  最近一段给xx做项目,这边最头疼的事情就是数据库入库瓶颈问题。

  • 环境

  服务器环境:虚拟机,分配32CPU,磁盘1.4T,4T,5T,6T几台服务器不等同(转速都是7200r),内存64G。

  • 排查步骤

  排查一:数据库恢复模式为简单模式,数据库和tempdb的初始大小。数据库文件初始化大小100G,日志文件初始化大小50G,两个文件都是自动增长(按10%);tempdb初始化大小10G*4个文件,日志5G*4个文件,两个文件都是自动增长(按10%),分布在两个磁盘中(但看了这篇文章后,有点傻眼了。);

排查二:设置数据库占用最大内存为30G;

排查二:数据库表删掉所有索引,除了PK(OID bigint,Time datetime)分区使用了Time字段(看了这篇文章,为后边担忧);

排查三:系统windows server 2008(Vista内核),升级为windows server 2008 R2 SP1(WIN7内核);

排查四:批量入库一次批量入库的次数,目前还在调整中,把BatchSize设置为一个合适的值,是50W,还是200W呢?(BCP原理篇

排查五:数据库连接字符串把172.21.xxx.xxx\work,修改为(local)\work或者.\work,是否可以采用共享内存的方式来建立连接呢?目前还未测试。(实战篇微软文档篇)


连接字符串参数:

Data Source

- 或 -

Server

- 或 -

Address

- 或 -

Addr

- 或 -

Network Address


默认值:

N/A


要连接的 SQL Server 实例的名称或网络地址。可以在服务器名称之后指定端口号:

server=tcp:servername, portnumber

指定本地实例时,始终使用 (local)。若要强制使用某个协议,请添加下列前缀之一:

np:(local), tcp:(local), lpc:(local)


连接字符串参数:

Network Library

- 或 -

Net


默认值:

‘dbmssocn‘


用于建立与 SQL Server 实例的连接的网络库。支持的值包括 dbnmpntw(命名管道)、dbmsrpcn(多协议)、dbmsadsn (Apple Talk)、dbmsgnet (VIA)、dbmslpcn(共享内存)及 dbmsspxn (IPX/SPX) 和 dbmssocn (TCP/IP)。

相应的网络 DLL 必须安装在要连接的系统上。如果不指定网络而使用一个本地服务器(比如“.”或“(local)”),则使用共享内存。

排查六:SqlBulkCopy参数SqlBulkCopyOptions设置

1. 有标识列的表
  1. 1 SqlBulkCopyOptions.KeepIdentity 必须设置!否则会出现复制过去的数据产生标识列发现变化的情况!
  1.2 如果原表的标识列即为主键, 那按1.1 的设置已足够。 如果原表无主键, 那在复制之前必须先清空原表(truncate table), 否则会出现多个相同的标识值的列!
2. 为NULL值的列
  2.1 SqlBulkCopyOptions.KeepNulls 必须设置!否则会出现源数据的字段为NULL时, 复制过去却成了默认值!

其它几个选项的说明与分析:
  Default 对所有选项使用默认值。
  KeepIdentity 保留源标识值。如果未指定,则由目标分配标识值。
  CheckConstraints 请在插入数据的同时检查约束。默认情况下,不检查约束。
  TableLock 在批量复制操作期间获取批量更新锁。如果未指定,则使用行锁。
  KeepNulls 保留目标表中的空值,而不管默认值的设置如何。如果未指定,则空值将由默认值替换(如果适用)。
  FireTriggers 指定后,会导致服务器为插入到数据库中的行激发插入触发器。 默认情况下, 是不激发触发器的……
  UseInternalTransaction 如果已指定,则每一批批量复制操作将在事务中发生。 在一个事务中执行,要么都成功,要么都不成功。

Default 就没有什么好说的了, 不要
KeepIdentity 和 KeepNulls 上面已有了, 不再分析。
CheckConstraints 不需要, 因为是现成的数据, 既然已在DB中, 必然是通过了约束检查的。
TableLock 不需要, 因为复制时两个库都需要处于单连接状态, 不可能有干扰。
FireTriggers 一般就不需要了吧, 毕竟只是复制数据, 而且是现成的数据……
UseInternalTransaction 关系也不大, 反正复制失败会记录到自定义的日志, 失败了也知道, 重来一次就可以了。

  • 别人给的建议

ETL来处理:

  针对这个解决方案,搜索了后才知道微软的SSIS中是支持ETL的(实战1实战2篇,微软文档篇)。具体需要测试才知道结果。

内存处理:

  就是把未能处理的数据放到内存中,使用Redis或者memcached来存储,之后把这样的数据源排队性的存储到sqlsever 2008 R2数据库中,该方案可行性还需要测试,到底需要多大的设备,一个上边同样配置的虚拟机能存储多少条记录会内存满负载,这是该方案是否成立的根本问题,问题是我们需要的是数据量在几百亿量级的数据,这样的情况需要测试才会有结论。

  另外,看到SqlServer2014(SQL 2014新功能介绍系列1 – 内存中 OLTP (In-Memory OLTP))也做了比较大的调整,基本上支持内存存储,可以异步快速存储到内存中,该方案以目前设备来说,恐怕行不通。

  其他,后来搜索过程中学习到了怎么实现一个复制的,复制的场景的应用模式(实战篇)。

用Oracle来替换SqlServer:

  该方案我也早想去这么去做,回去就给公司建议,不过公司一定会PASS的。。。

参考资料:

DBA博客:http://www.cnblogs.com/CareySon/archive/2012/05/08/2489748.html

DBA问题查找经验总结:http://blog.csdn.net/yynetsdk/article/details/6749529

SqlBulkCopy 实现原汁原味复制的注意事项:http://blog.csdn.net/yenange/article/details/35837247

时间: 2024-10-29 19:12:29

SqlServer批量复制(bcp)[C#SqlBulkCopy]性能极低问题的相关文章

【转】批量复制操作(SqlBulkCopy)的出错处理:事务提交、回滚

原文地址:http://blog.csdn.net/westsource/article/details/6658109 默认情况下,批量复制操作作为独立的操作执行. 批量复制操作以非事务性方式发生,不可能使其回滚. 如果需要在出错时回滚全部批量复制或它的一部分,可以使用 SqlBulkCopy 托管的事务,在现有事务中执行批量复制操作,或者在 System.Transactions Transaction 中登记它. 由于不同批次在不同事务中执行,因此,如果在批量复制操作期间发生错误,则当前批

SqlBulkCopy(批量复制)使用方法 && SqlDataAdapter Update

SqlBulkCopy提供了一种将数据复制到Sql Server数据库表中高性能的方法.SqlBulkCopy 包含一个方法 WriteToServer,它用来从数据的源复制数据到数据的目的地. WriteToServer方法可以处理的数据类型有DataRow[]数组,DataTable 和 DataReader. 你可以根据不同的情形使用不同的数据类型.SqlBulkCopy其原理是采用了SQL Server的BCP协议进行数据的批量复制. SqlBulkCopy(批量复制):批量复制速度极快

SqlBulkCopy(批量复制)使用方法

轉載: SqlBulkCopy(批量复制)使用方法 Posted on 2011-02-16 11:01 宽田 阅读(3510) 评论(0) 编辑 收藏 SqlBulkCopy提供了一种将数据复制到Sql Server数据库表中高性能的方法.SqlBulkCopy 包含一个方法 WriteToServer,它用来从数据的源复制数据到数据的目的地. WriteToServer方法可以处理的数据类型有DataRow[]数组,DataTable 和 DataReader. 你可以根据不同的情形使用不同

使用asp.net 2.0中的SqlBulkCopy类批量复制数据

介绍:在软件开发中,把数据从一个地方复制到另一个地方是一个普遍的应用. 在很多不同的场合都会执行这个操作,包括旧系统到新系统的移植,从不同的数据库备份数据和收集数据. ASP.NET 2.0有一个SqlBulkCopy类,它可以帮助你从不同的数据源复制数据到SQL SERVER数据库. 本文中我将示范SqlBulkCopy类的不同应用. 数据库设计: 这个数据库的设计还是蛮简单的,它基于Northwind数据库的Products表.另外我还在Northwind数据库中创建了3个表. 详情可以看一

使用SqlBulkCopy类来批量复制数据

DataTable dt = new DataTable(); dt.Columns.Add("id", typeof(string)); for (int i = 0; i < 100; i++) { DataRow dr = dt.NewRow(); dr["id"] = "sadf" + i; dt.Rows.Add(dr); } using (SqlConnection conn = new SqlConnection(@"

SQLIOSim 模拟SQLServer的行为来测试IO性能

SQLIOSim 功能: 模拟SQLServer的行为来测试IO性能. SQLIOSim的版本: (1) SQL Server 2005的SQLIOSim是需要上网下载的套件. (2) 从SQL Server 2008开始,SQLIOSim会包含在SQL Sever安装内.对于SQL Server 2008 R2,该应用程序所在目录为C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\Binn. (3) SQLIO

linux批量复制或删除同命名规则的文件

如图所示,有多个不同后缀的文件,但他们的前缀都是"QC_TZ.impute." 此时想批量复制图中的文件的话,可以考虑用命令行 cp QC_TZ.impute.* /your/destination/ 其中,cp表示复制,*表示不同的后缀,/your/destination/表示复制的文件存放在"destination"的文件夹下 同理,如果想批量删除的话,用以下命令行 rm QC_TZ.impute.* rm表示删除

批量复制文件无密码输入

无密码输入批量复制文件 作用:批量复制:复制单个文件或者压缩包到多台服务器,无密码输入<我用着挺方便的> 名称:scp_file.py 环境:需要有Python,需要paramiko <在管理机上安装,一劳永逸> 执行方式: ./scp_file.py iplist src_file dst_file 说明: iplist:ip列表 src_file:绝对路径下的文件 例如:/tmp/test.txt dst_file:绝对路径下的文件 例如:/data/log1.txt 备注:复

批量复制文件

1 #!/bin/bash 2 #批量复制文件到指定的目录 3 #需求:有很多文件需要在一个文件目录查找到相对应的文件,然后把它复制到新建目录 4 #方法1:find /media -name 'a'* |xargs -I [] cp [] /mnt 5 #方法2:进入存放文件目录执行 ls|grep a |xargs -I [] cp [] /mnt 6 #方法3:首先新建一个txt文件,把表名写进去,然后执行下面脚本 7 for file in `cat a.txt`;do 8 a=`ls|