首页 新闻 会员 周边

请教sqlserver大量数据中部分数据(仍然大量,多表)导入导出解决思路

0
悬赏园豆:100 [已解决问题] 解决于 2014-06-10 15:25

  在项目(C#和sqlserver2012)里有个需求是把数据库中存储的一些信息导出为文件(任意格式)以存档,并要求能够将导出去的数据重新导入到数据库(与原始数据库结构完全相同的另一个数据库,专门用来存放导入的数据)中以临时查看存档的数据。数据库中分为 A B C三个部分,分别导出其中满足查询结果的数据,每部分包含多张表,有部分表数据量很大,这部分表大概一次导出操作要保存百万条数据以上千万以下,这部分数据的文件大小1G左右的。

  我的问题是,用C#代码完成以下操作:

  (1)如何能够导出数据的同时把数据库的结构也保存到导出的文件中,以便于再导入时能够恢复原来的状态(比如满足参照完整性)。

  (2)如何能够高效的导出(导入)这么大量数据。

  我想过的方案:

  (1)最开始,想过把数据查到一个DataSet里面,再把这个DataSet序列化到硬盘上,导入的时候把这个逆序列化为DataSet再保存到数据库中。但是这个感觉方案肯定不行,因为这个DataSet首先要载入内存,一次把GB级数据载入到内存效率太低。想以流的形式把数据到出去,又不知道怎么做。

  (2)把数据导出为xml或excel,导入的时候一条一条的解析,但是这需要我自己维护导出了哪些数据的信息。

  (3)把数据在sqlserver服务器上复制到另一个临时数据库中,把这个临时数据库分离,保存分离出的文件。要想导入的时候,再附加这个数据库。这个可行吗?请各位大侠不吝赐教。

 

  小生刚刚学C#,苦于无经验困扰,烦请各位指个明路,谢谢。

zhang ming的主页 zhang ming | 初学一级 | 园豆:116
提问于:2014-05-11 16:35
< >
分享
最佳答案
1

一两个G的数据最好是用数据库。 

1:clone一个同样的空数据库。

2:定期将要保存的数据导入到克隆的数据库中对应的表中。

3:对克隆数据库进行备份,备份成功后清空克隆数据库。

4:每次重复以上2,3步骤

因为一两个G数据也不算少,建议用SQL计划或WIN服务 在空闲时间定时执行。

收获园豆:50
Hyman.Ro | 菜鸟二级 |园豆:275 | 2014-05-11 20:49

  要保存的数据是临时决定的。就是说系统使用时由使用者来选择要保存的数据,然后保存。所以没法用自动化的定期操作。

  我考虑过这个做法,就是还没想好克隆的数据库怎么再度访问。先克隆一个数据库,数据克隆后,让数据库离线,然后保存mdf文件,然后怎么再度访问这个mdf文件呢?还原还是新建一个数据库把数据库文件指向这个文件?我还要好好查查。

zhang ming | 园豆:116 (初学一级) | 2014-05-11 20:58

你把克隆数据库备份为bak文件,需要用这个文件里的数据的时候 把这个文件还原到指定的新数据库就可以了。所以正常来说应该有3个数据库。 一个业务库,一个临时库,一个查阅库。要倒数据库的时候业务库倒到临时库,要查阅的时候 用临时库备份的文件还原到查阅库。这样相互不影响,程序上处理,也就是对应哪个数据库连接了。

Hyman.Ro | 园豆:275 (菜鸟二级) | 2014-05-11 21:09

@Hyman.Ro: 这个方案感觉很完整,也很具有可操作性。非常感谢。我再考虑一下,如果合适的话,就这个方案了。

zhang ming | 园豆:116 (初学一级) | 2014-05-11 21:12

@zhang ming: 不客气。顺便提醒一下,你的数据量大,可以的话,建议压缩备份出来的BAK文件,节省磁盘空间,使用的时候再解压。至于压缩与解压的代码网上很多,我就不多讲了。希望对你有帮助。

Hyman.Ro | 园豆:275 (菜鸟二级) | 2014-05-11 21:22

@Hyman.Ro: 嗯!我再去查查。谢谢。

zhang ming | 园豆:116 (初学一级) | 2014-05-11 21:24
其他回答(5)
1

看了以上的需求,想起客户的话,这个很简单,哒哒哒哒哒.....最后给了句,你看看三天能完成吗?

我们看了三天,还没看出咋完成,哈哈...

你的需求如果是具体的特定的数据库,倒是好办,但是要通用的解决方案就麻烦了。

1、2、3基本都可以,不过1、2要修改为50条数据或是100条数据一保存,全部保存不现实,一条条保存太慢。

要考虑到参照完整性的话,数据导入一定要有特定的顺序。主表先导,再到子表。

不管你是保存为XML、EXCEL还是Sqlite还是Access或是MDF,这个都不重要,关键还是导入导出的代码。

感觉这种事情不会经常进行啊,哪家公司无聊了整天这么折腾数据啊,一年搞个一次差不多了。

收获园豆:10
爱编程的大叔 | 园豆:30839 (高人七级) | 2014-05-11 16:50

  就是说可以自己来实现流式的保存数据,然后自己维护导出数据的结构信息。导入的时候根据这个结构信息来确定怎么导入数据。对吧?我主要考虑的是,有没有一种专门为了这个操作的机制,我可以简单调用的,主要是这种机制一般优化过,效率比我这种初级开发者高。像sqlserver有个bcp可以用来导入导出,但是需要你自己记住导出了哪张表,导入的时候才知道把哪个文件导入到哪张表中。且比较快。因为整个过程都是在数据库那边执行的。  

  是特定的数据库,sqlserver2012。不需考虑通用性的问题。

  是特殊行业,海量数据对他们来说是家常便饭。是否常用不需要考虑啦,考虑的是用到的时候怎么更快的完成操作。

  我也想起同学的一句话:需求无非两种,这也需要做?!这也能做?!

  

支持(0) 反对(0) zhang ming | 园豆:116 (初学一级) | 2014-05-11 17:25

@zhang ming: 

对我来说,是否常用,什么时候用,为什么用这也是重要的数据,这也是设计软件的一个重要参考。

如果是为了常用数据库不至于过大,所以要将过期数据(三个月或是半年或是一年)的数据移出,

可以考虑建立后备数据库(长期在线,比如201101表示2011年第一季度的数据),然后软件可以连接到不同的帐套查询。如果还要更方便一些的,可以考虑有年份数据,也有季度数据。这样软件可以连接到不同的期间数据库进行查询,这样需要查询的时候,不用等待数据的导入。(空间换取时间,因为后备数据库可能用到的机会不大,可以随便找个服务器放下就行。)

感觉上你已经跳过了最初为什么要实现这个功能的那步,直接给了解决方案,希望我上面说的可以给你一些启发。

支持(0) 反对(0) 爱编程的大叔 | 园豆:30839 (高人七级) | 2014-05-11 21:02

@爱编程的大叔: 这里的导出是为了存档备案,以备将来的检查。不是为了避免数据库过大。虽然按这个增长速度确实会过大,但是这个需求不是为了解决数据库过大这个问题的。

支持(0) 反对(0) zhang ming | 园豆:116 (初学一级) | 2014-05-11 21:09

@爱编程的大叔: 您说的很有道理。抱歉我一开始没说清楚,这个需求是为了存档备案。且我目前没有设计软件整体架构的权限,还处于实现设计好的功能模块的阶段。很感谢您提的建议。

支持(0) 反对(0) zhang ming | 园豆:116 (初学一级) | 2014-05-11 21:22
0

直接双击热备.

迅捷网络[来送福利] | 园豆:576 (小虾三级) | 2014-05-11 17:21

目的不是灾备喔,而是筛选部分数据存档。且可查看存档的文件(通过再倒入数据库来实现)

支持(0) 反对(0) zhang ming | 园豆:116 (初学一级) | 2014-05-11 17:27

@zhang ming: 建议不用文件.直接另一个用数据库.因为需求的根本不是用文件,而是指定的备份及还原

sqlbulk可以解决批量插入工作.

支持(0) 反对(0) 迅捷网络[来送福利] | 园豆:576 (小虾三级) | 2014-05-11 17:31

@Moon.Orm塑造Orm经典: 要的就是文件,需求需要把文件单独保存起来。像档案一样保存起来。后面还要再查看这个数字档案。

支持(0) 反对(0) zhang ming | 园豆:116 (初学一级) | 2014-05-11 17:36

@zhang ming: 这是一伪需求.

支持(0) 反对(0) 迅捷网络[来送福利] | 园豆:576 (小虾三级) | 2014-05-11 17:37

@zhang ming: 我想问问难道.sql .mdf不是文件?

支持(0) 反对(0) 迅捷网络[来送福利] | 园豆:576 (小虾三级) | 2014-05-11 17:38

@Moon.Orm塑造Orm经典: sql.mdf是文件啊。可是别人一次产生的数据一两个G,按这个速度增长,我要是保存mdf文件的话,每次保存都保存的是整个数据库。到后面mdf文件到几百个G的时候还这么保存那不慢得根本无法接受啊。可能说我没说清楚,需求的本意是:抽取数据库中某段时间内的某部分数据,并存档这部分数据。我想的解决方案的表现形式是“导出”为文件,存档这份文件。并且将来要能够重新查看着部分存档的数据。我想的是能够按数据原本在数据库中的形式重新保存到专门的导入数据数据库中,这样就能够按查看原始数据库中数据的方式查看数据了。但是不知道怎样实现起来效率更高。

支持(0) 反对(0) zhang ming | 园豆:116 (初学一级) | 2014-05-11 19:01
2

额,这个直接用SQL Server自带的SSIS不就行了?导入导出无任何压力,特别是大数据量下,然后在C#里面直接调用SSIS就可以了(SSIS提供了.NET的API,我们可以很方便的在.NET程序中调用)。

收获园豆:30
ocean | 园豆:824 (小虾三级) | 2014-05-12 10:00

刚刚去看了一下SSIS,觉得不理解它的机制,是说这是一个提前规划好的任务包,在需要的时候告诉数据库让数据库执行吗?如果我需要通过某些参数(比如起止时间)来确定要导出哪些数据,那这个参数怎么传入到这个包里面。

支持(0) 反对(0) zhang ming | 园豆:116 (初学一级) | 2014-05-12 10:55

@zhang ming: SSIS本身就支持参数,SSIS连内嵌C#代码都可以,何况与参数这种通用需求了。SSIS实际上就是Sql server集成服务提供的一个包,这个包包含了数据导入导出的操作,可以对导入导出每个步骤进行精确的控制。通常SSIS的包放在SQL Server的代理服务中进行定时运行。当然因为提供了.NET API所以可以直接在C#中调用运行SSIS包。

支持(0) 反对(0) ocean | 园豆:824 (小虾三级) | 2014-05-19 14:34
0

按照你的需求,新建一个数据库,写相关的数据导出语句,视机器性能和网络状况,考虑是在另外一台服务器上弄还是在同一台服务器上弄。用作业定时执行或者手动执行导出过程,然后就备份这个新数据库,导出备份的工作就完啦~~~

导入时,同样是写好相关的数据导入语句,最简单的是导出时的数据结构和导入时的一样,这样就不用转换,直接可以查询使用了。

这样你的数据可能是这样的:主数据库maindata,备份数据库bkdata20140512、bkdata20140513……如果你的数据备份很简单,可以不多个数据库,而是在同一个数据库里用不同时间戳的表,然后半年或者一年再备份一次整个备份数据库。

收获园豆:10
不能飚车 | 园豆:453 (菜鸟二级) | 2014-05-13 15:16
0

redgate 有一个轻量的数据导入导出工具  并有压缩备份功能.

gunsmoke | 园豆:3592 (老鸟四级) | 2014-05-15 11:22
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册