現在有一個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;
}
不考慮什麼安全,就使用最簡單的字符串拼接。採用一個for循序,遍歷所有數據,拼湊代碼如下:
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