现在有一个2000万级别的数据量的数据库,数据存在sqlserver 20008中。想要将此数据转移到mongdb中。网上有看说有个工具可以将mysql的数据直接转移到mongodb中,但是又要将sqlserver 2008数据先转移到mysql中,各种折腾后,各种试验,楞是没能成功,一怒之下,自己动手写程序来做这个数据迁移。
之前有讲到mongodb一次性插入10000数据的效率,确实很快,然后也测试了下,从sqlserver 一次性选择10000条数据也是在1秒之内,想想,干脆一不做二不休,写了一个程序,采取for循环 每次从数据库取10000条,然后插入mongdo,直到循环完所有数据。2000万条数据,对于计算机而言,小事啊 为了这个,特意做了下效率问题,测试了下,一次循环下来,3秒之内能解决,算算,一分钟就是20万数据,二个小时就可以完全搞完。(事实也确实如此,一个多小时搞定了,早知道如此,就不要花了那么多时间去找工具,找各种导出教程,各种纠结,各种安装);
数据库结构很简单,是一个比较出名的某某hotel的数据,纯学术研究。
程序代码我放在这里了:有兴趣的朋友可以看看。勿喷。如果你有更好的办法。欢迎留言;
CSDN git 仓库地址:
[email protected]:chenqiangdage/sqltomongo.git
项目地址:
https://code.csdn.net/chenqiangdage/sqltomongo/tree/master
程序每次从sqlserver 中取10000条数据。之所以这样,因为改表主键id是连续而且从1开始。所以每次循序取10000条,这样就能保证取到所以的数据了。
public static DataSet SelectData(DataSet dt,string query) { cmd = new SqlCommand(query, sqlconnection); SqlDataAdapter sda = new SqlDataAdapter(cmd); sda.Fill(dt); return dt; }
string querystr = @"SELECT id,[Name] ,[CardNo],[CtfTp],[CtfId] ,[Gender] ,[Birthday] ,[Address] ,[Zip] ,[District2] ,[District3] ,[District4],[Mobile],[Tel],[Fax],[EMail],[Version] FROM [testdb].[dbo].[cdsgus] "; Stopwatch sw1 = new Stopwatch(); Stopwatch sw2 = new Stopwatch(); for (int i = 0; i <= 20050154; i = i + 10000) { DataSet dt = new DataSet(); sw1.Start(); string tempquery = ""; tempquery = querystr + " where id between " + (i + 1) + " and " + (i + 10000); dt = SqlServerHelp.SelectData(dt,tempquery); dus = ConstructMongoDocuments(dt); Console.WriteLine("from " + (i + 1) + " to " + (i + 10000)+" is ready! "); MongoHelp.Insert10000Documents(dus); sw1.Stop(); TimeSpan ts1 = sw1.Elapsed; Console.WriteLine("Done! cost time : "+ts1.TotalMilliseconds); sw1.Reset(); System.Threading.Thread.Sleep(10); System.GC.Collect(); }其中ConstructMogoDocuments方法是凑成mongodb插入多数据所需的文档集合;
解释下,这里在不断调用gc.collect()是因为程序占用内存太多了,按照回收机制,程序里面的dataset在一次for循环完了后,这个小程序里面已经没有引用指向这块内存,但是gc.collect()好像并不回收这块内存。可能的原因Mongodb非常占用内存,插入试验中,有不断对程序申请的内存做主动回收处理,可发现,尽管调用回收,可内存依旧没有降下去,说明程序中占用的内存还有引用指向了这块数据内存,而且监控发现,从100万数据到500万数据这个过程中,db所在的文件夹所占用的5个数据文件大小就没变过,于是我在想,有必要去看看源代码了,大胆猜测它是先开辟一块2g的存储空间,然后不断的往这块空间里填数据,而这些数据一直在内存里!这是gc回收一直没有收回的原因!
有趣的是程序打印显示插入10000笔数据用时1秒多,而实际观测远远不止1秒才打印出来,说明它插入的不是先往文件存储区域,应该是到内存中,在由mongo程序写入存储位置。这打印出来的1秒实际是写入到内存所用时间。在数据插入到700万左右,生成了一个2g文件 *****.6 也证实了之前的猜测;
截图如下。
最后程序大概跑了1个多小时;同样的一份数据,在sqlserver 2008中。占用了7.88g空间。而在mongodb中,占用了13.3G空间。这玩意占用空间真不小;
http://download.csdn.net/detail/chenqiangdage/9313687