我今天抽時間對該數據庫進行了一些了解,也下載了它的完整源代碼,還不及細看,但它的架構很不錯,下午在看的時候有一個重要的方面對我觸動挺大。我暫時不做太多的評論,但不否認地說,我的第一印象就是眼前一亮。
db4o是一個面向對象的數據庫,雖然這個概念並不新,但我覺得概念新不新並不重要,db40能被開發出來,而且做的確實很不錯,這本身很值得欣賞。我自己也是覺得,實踐和時間才是檢驗真理的唯一標准,要敢於動手。呵呵
我想很多朋友都比較關心,如果用XML存儲數據,那麼性能怎麼樣,會不會很慢呢?我在上一篇文章的評論中多次強調以下幾點
1. 據我的經驗,讀取本地磁盤文件,通常比讀取真正的關系型數據庫要來得快。
2. XML文件本身不是慢的原因,如果慢的話,則需要考慮更好的設計。而且XML提供了很好的編程接口,其實它反倒是比別的文件有更好的優勢。例如,你可以假想一下,你如果要讀一個平面文件(例如ini文件),或者CSV文件的情況,那可能就更慢了。
對照db4o提供的官方學習材料(很不錯的,贊一個先),我做了一些練習。db4o的數據庫文件只有一個,是二進制格式的。但即便在大容量寫入和讀取的時候,性能表現也很不錯。這一點就是看出算法的重要性了。我為什麼要這麼說呢,因為要在一個文件中,抽取出來特定的部分,往往都是相當不容易的。二進制的讀寫問題本身就是毀譽參半的。
大家試想一下吧,如果一個文件已經有1GB,然後我要在期間一半的位置寫入另外一個對象(例如要修改),這將是一間非常不容易的事情,因為所有內容都在一個文件裡面。坦白地說,這也就是我為什麼要開發這個XML數據庫的根本原因吧。我覺得如果還是用獨立的一個或者為數很少的幾個二進制文件,那麼與傳統的關系型數據庫就區別不大了,而且再怎麼優化,估計還是有瓶頸的。
我當然沒有辦法猜想到db4o的開發小組當時的考慮,也許在當時這是一個比較好的方案。
為了說明這個問題,我寫了一個簡單的演示程序來對db4o和XML數據庫的大容量寫入和讀取進行對比。我分別向他們插入100000(十萬)個對象。然後又各自讀取了將近35000(三萬五千)個對象。
第一部分:業務實體類(這是摘自db4o的文檔) /// <summary>
/// 這是一個很簡單的類型,摘自db4o的官方案例
/// </summary>
public class Pilot
{
public Pilot() { }
string _name;
int _points;
public Pilot(string name, int points)
{
_name = name;
_points = points;
}
public string Name
{
get
{
return _name;
}
set { _name = value; }
}
public int Points
{
get
{
return _points;
}
set { _points = value; }
}
public void AddPoints(int points)
{
_points += points;
}
override public string ToString()
{
return string.Format("{0}/{1}", _name, _points);
}
}
第二部分:測試代碼 class Program
{
static void Main(string[] args)
{
//這個測試程序主要用來比較與db4o這個數據庫的操作及姓能上的差別
//創建db4o數據庫,並插入100000(十萬個)對象
Console.WriteLine("db4o數據庫測試結果");
IObjectContainer db = Db4oFactory.OpenFile("test.yps");
try
{
Stopwatch watch = new Stopwatch();
watch.Start();
for (int i = 0; i < 100000; i++)
{
Pilot pilot1 = new Pilot("Michael SchuMacher", i);
db.Store(pilot1);
}
watch.Stop();
Console.WriteLine("\t插入1000000個對象,耗時:{0}秒", watch.ElapsedMilliseconds / 1000);
watch.Start();
var query = from p in db.Query<Pilot>()
where p.Points % 3 == 0
select p;
Console.WriteLine("\t讀取{0}個對象", query.ToArray().Count());
watch.Stop();
Console.WriteLine("\t讀取耗時:{0}秒", watch.ElapsedMilliseconds / 1000);
}
finally
{
db.Close();
}
Console.WriteLine("XMLDatabase測試結果");
//創建XMLDatabase,並插入100000(十個)對象
using (XDatabase xdb = XDatabase.CreateInstance("Test", "E:\\Temp")) {
try
{
Stopwatch watch = new Stopwatch();
watch.Start();
XTable<Pilot> table = xdb.Create<Pilot>("Pilots", new[] { "Name" });
for (int i = 0; i < 100000; i++)
{
Pilot pilot1 = new Pilot("Ares Chen", i);
table.Insert(pilot1);
}
xdb.SubmitChanges();
watch.Stop();
Console.WriteLine("\t插入1000000個對象,耗時:{0}秒", watch.ElapsedMilliseconds / 1000);
watch.Start();
var query = from p in table.Select()
where p.Points % 3==0
select p;
Console.WriteLine("\t讀取{0}個對象",query.ToArray().Count());
watch.Stop();
Console.WriteLine("\t讀取耗時:{0}秒", watch.ElapsedMilliseconds / 1000);
}
finally
{
}
}
Console.Read();
}
}
第三部分:測試結果
我將執行順序倒過來,再執行一次,結果如下
第四部分:文件比較
XML數據庫是每個表單獨存放一個XML文件(我還在考慮如何分布式存放,例如一個表可以有N個XML文件),插入這一百萬個對象之後,大約是4.08MB
而且該文件,就是一個很直觀的XML文件
而db4o是將所有對象放在一個數據庫文件的,文件名是無關緊要的。
它的文件大小為9.07MB左右
而該文件是一個典型的二進制文件,如果我們一定要打開來看,大致如下
【備注】以上的對比是作為技術研究目的而做的。其實我前面就分析過了,db4o使用一個二進制文件的方式來做,有這樣的性能已經是很了不起的了,它的算法應該是很不錯的。我還不知道它是否支持多個文件,因為看它的文檔說它最大支持的單數據庫大小為250GB(這有點雷人,但我斷定不可能有人這麼用的),如果說250GB的數據,全部在一個文件裡面的話,這太可拍了。
最後,用一個文件存儲所有的數據庫並無一無是處。它的一個最大的好處就是備份和管理方便,因為就只有一個文件。而正在開發的XML數據庫,這方面就會有劣勢,因為我的想法是通過不同的目錄保存不同的東西,例如Tables裡面放所有的表數據,Schemas裡面放所有的架構文件,Blobs裡面放所有的大對象(例如圖片),還有一個專門的rels目錄,記錄了這些文件的關系。這樣一來就會有一些風險,因為文件很多。這方面還需要多思考思考。
XML數據庫的開發工作在繼續進行,大家有什麼好的建議和想法,我歡迎留言。由於日常我還有其他的工作要忙,一般晚上再統一回復吧。