2012-09-10 89 views
3

我正在使用db4o 8.0。 db4odatabase文件大小爲21MB。 數據庫中包含以下對象。db4o碎片整理刪除數據庫中的所有對象

User : There is 1 user in db. 
PostedMessage : There are 10000 postedMessages in db. 

我刪除了所有10000個發佈的消息。然後我嘗試對db4o數據庫進行碎片整理。以下代碼用於碎片整理。

private void processDefrag() { 
    try { 
     String dbpath = "D:\\db4oDatabase"; 

     IdMapping mapping = new InMemoryIdMapping(); 
     //new DatabaseIdMapping(dbpath); //use this if heap overflows 

     DefragmentConfig config = new DefragmentConfig(dbpath, dbpath+".bak", mapping); 
     config.storedClassFilter(new AvailableClassFilter()); 
     config.forceBackupDelete(false); 
     config.objectCommitFrequency(1000); 
     Defragment.defrag(config); 
     System.out.println("Defrag completed"); 

    } catch (IOException ex) { 
     ex.printStackTrace(); 
    } 
} 

我的期望是,db4oDatabase文件大小將回到21 KB。而db4oDatabase將仍然包含1個用戶對象。但是,在運行上述代碼之後,db4odatabase將變爲完全空的。爲什麼會發生這種情況?

如何避免丟失未刪除的其他對象(本例中爲1個用戶對象)?什麼是在db4o數據庫上進行碎片整理的正確方法?

+0

我假設你將對一個更大的數據庫進行碎片整理,因爲21 MB的磁盤可能只需要0.2美分的成本。即它不值得。 –

+0

這段代碼是否可以訪問'User'類?也就是說,如果你調用['Class.forName(「com.mypackage.User」);'](http://docs.oracle.com/javase/6/docs/api/java/lang/Class.html#forName %28java.lang.String%29)在這個代碼中與你的用戶類'FQCN,它會拋出一個異常嗎? – Brian

+0

@Peter:我在開發過程中使用21 MB數據庫,僅用於測試目的。在生產過程中,預計將達到3至4 GB甚至更大。 –

回答

2

如果由於無法找到它而無法接受該課程,則可以嘗試編寫自己的StoredClassFilter,它只接受所有StoredClass對象。

public class AcceptAllClassFilter implements StoredClassFilter { 

    @Override 
    public boolean accept(StoredClass storedClass) { 
     return true; 
    } 
} 

然後:

config.storedClassFilter(new AcceptAllClassFilter()); 

這將工作,除非磁盤碎片整理程序只是刪除一切,而不需要自動將StoredClass。如果是這種情況,我們可能需要找出爲什麼User類沒有相應容器的StoredClass實例。

0
public static void printStoredClasses(ObjectContainer db) { 
    StoredClass[] storedClasses = db.ext().storedClasses(); 
    for (StoredClass sc : storedClasses) { 
     try {   
      Class<?> c = Class.forName(sc.getName()); 
      DebugMessagePrinter.print(c.getName()); 
     } catch (ClassNotFoundException ex) { 
      ex.printStackTrace(); 
     } 
    } 
} 

我用上面的方法打印存儲的類。正如Brian猜測的那樣,出於某種原因,它沒有打印User和PostsMessage類名。這意味着它無法在db4o數據庫文件中看到這些類。

0

最後,在Brian的AcceptAllFilter類的幫助下,我可以成功地對db4oDatabase文件進行碎片整理。大小從21 MB減少到12MB。工作方法如下所示。

private void process() { 
    try { 
     String dbpath = "D:\\db4oDatabase"; 
     printStoredClassNames(dbpath); 

     IdMapping mapping = new InMemoryIdMapping(); 
     //new DatabaseIdMapping(dbpath); //use this if heap overflows 

     DefragmentConfig config = new DefragmentConfig(dbpath, dbpath+".bak2", mapping); 
     config.storedClassFilter(new AcceptAllClassFilter()); 
     config.forceBackupDelete(false); 
     config.objectCommitFrequency(1000); 
     config.db4oConfig().add(new UuidSupport()); 
     Defragment.defrag(config); 
     System.out.println("Defrag completed" + t.s()); 

    } catch (IOException ex) { 
     ex.printStackTrace(); 
    } 
} 

順便說一句,碎片整理似乎並沒有做到最好。刪除10000個已發佈的消息對象後,數據庫僅包含1個用戶對象。我希望數據庫文件大小以KB爲單位。

但是,正如他們所說,有些事比沒有好。有了這樣的成功,我會繼續尋找更好的碎片整理。如果我碰巧得到更好的結果,我會在這裏發佈。

相關問題