1 2 3 4 5 6 7 8 |
/user_c/ /user_c/application/ /user_a/log/user_c/ /user_a/log/webserver/ /user_b/ /user_b/application/ /user_b/log/ /user_b/log/webserver/ |
那麼當我想要知道 /user_c/ 這個資料夾有哪些檔案和資料夾時,MongoDB 可以多快幫我找出來?
首先是隨機產生資料,我用隨機產生的 UUID 產生一百萬個不重複的 UUID 來當做檔名
然後用 Random 隨便決定一個目錄來放這個檔名,產生的資料先暫存在 ArrayList 上。
程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
String[] basicPathArray = { "/user_c/" , "/user_c/application/" , "/user_a/log/user_c/" , "/user_a/log/webserver/" , "/user_b/" , "/user_b/application/" , "/user_b/log/" , "/user_b/log/webserver/" }; int length = 1000000 ; // Initial list. ArrayList<String> parentList = new ArrayList<String>(length); ArrayList<UUID> uuidList = new ArrayList<UUID>(length); // Create path list. Random rand = new Random(); HashMap<UUID, Boolean> maps = new HashMap<UUID, Boolean>(); for ( int i= 0 ; i<length ; i++) { // Create UUID UUID uuid = UUID.randomUUID(); while (maps.containsKey(uuid)) uuid = UUID.randomUUID(); // Record the UUID maps.put(uuid, true ); // Add to list parentList.add(basicPathArray[rand.nextInt(basicPathArray.length)]); uuidList.add(uuid); } |
插入資料時,將檔名與路徑分開存放,這樣在處理時應該可以加快取出資料的速度。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// Connect to MongoDB. Mongo mongo = new Mongo(); DB db = mongo.getDB( "mongo_test" ); DBCollection dbColl = db.getCollection( "performance" ); for ( int i= 0 ; i<parentList.size() ; i++) { // Construct resource dbo = new BasicDBObject(); dbo.append( "parent" , parentList.get(i)); dbo.append( "name" , uuidList.get(i).toString()); // Insert dbColl.insert(dbo); } |
因為要測試索引的效果,因此要設定索引。
1 2 3 4 |
// Create index BasicDBObject indexDbo = new BasicDBObject(); indexDbo.append( "parent" , 1 ); dbColl.ensureIndex(indexDbo); |
搜尋資料時,我的設定是搜尋路徑開頭是 /user_c/ 的資料,也就是目標會搜尋出所有 /user_c/ 的檔案和資料夾。
這裡用的搜尋方法是用 Regular Expression 搜尋以 /user_c/ 作為開頭的資料
即使用 {"parent": {"$regex" : "^/user_c/"}} 作為搜尋的參數。
1 2 3 4 5 6 |
BasicDBObject dbo = new BasicDBObject(); dbo.put( "parent" , Pattern.compile( "^" + basicPathArray[ 0 ])); cursor = dbColl.find(dbo); while (cursor.hasNext()) { DBObject obj = cursor.next(); } |
這裡比較特別的地方是,因為我最終是需要所有以 /user_c/ 作為開頭的資料
因此衡量時我是直接衡量 find() 指令的時間加上尋訪所有找到的文件的時間。
最後得到的結果如下:
1 2 3 4 5 6 7 8 9 10 |
Find /user_c/ size: 250239 Test insert and search without index Insert spent: 34476ms Find /user_c/: 1524ms --------------------------------------- Test insert and search with index Insert spent: 37760ms Create index: 19226ms Find /user_c/: 1211ms |
插入資料的時間其實顯示出來沒什麼意義因為兩者插入資料的方法是一樣的 XD
(我的索引是在資料插入完以後才建索引 XD)
不過可以看出在 100 萬筆資料下面,建索引花了 19 秒的時間~
而搜尋以 /user_c/ 開頭的路徑,未建索引是 1.524 秒、建了索引是 1.211 秒。
接著再做第二次測試,這次把建索引提前到插入之前先建,來看看建了索引以後才插入資料的時間差異。
1 2 3 4 5 6 7 8 9 10 |
Find /user_c/ size: 250142 Test insert and search without index Insert spent: 33597ms Find /user_c/: 6658ms --------------------------------------- Test insert and search with index Create index: 252ms Insert spent: 63218ms Find /user_c/: 1222ms |
這次可以明顯看出,有了索引之後,插入的速度會變慢~測了幾次,平均來說變慢的幅度大概也在一倍以內
而這次搜尋的結果則是呈現有索引比沒有索引快三到四倍。
其實每次跑數據都不太一樣,但以搜尋來說,有索引通常會快 30%~300% 不等的程度
一般好像落在大概 70% 上下比較多吧(純感覺 XD)。
參考資料:
1、MongoDB与内存
沒有留言:
張貼留言