我不是這方面的專家,在DB4O論壇上發帖可能會很好,但我認爲我有一個解決方案。它涉及不使用LINQ和使用SODA。
這就是我所做的。我創建了一個快速項目,根據您的博文的定義使用30000 SimpleObject填充數據庫。然後我寫了一個查詢來獲取所有SimpleObjects從數據庫中:
var simpleObjects = db.Query<SimpleObject>(typeof(SimpleObject));
當我纏它秒錶,該運行大約需要740毫秒。然後我使用你的代碼搜索0到2999之間的100個隨機數。響應是772毫秒,所以基於這個數字,我假設它將所有對象從數據庫中提取出來。我不確定如何驗證,但後來我認爲我已經用性能證明了它。
然後我就降低了。根據我的理解,DB4O團隊的LINQ提供者只是將其轉換爲SODA。因此,我想我會寫一個SODA查詢來測試,而我發現對一個屬性使用SODA對性能不利,因爲它需要執行19902毫秒。下面是代碼:
private SimpleObject[] GetSimpleObjectUsingSodaAgainstAProperty(int[] matchingIds, IObjectContainer db)
{
SimpleObject[] returnValue = new SimpleObject[matchingIds.Length];
for (int counter = 0; counter < matchingIds.Length; counter++)
{
var query = db.Query();
query.Constrain(typeof(SimpleObject));
query.Descend("Id").Constrain(matchingIds[counter]);
IObjectSet queryResult = query.Execute();
if (queryResult.Count == 1)
returnValue[counter] = (SimpleObject)queryResult[0];
}
return returnValue;
}
所以想爲什麼會這樣不好,我決定不使用自動實現的屬性,並將其定義我自己,因爲屬性實際上是方法,而不是值:
public class SimpleObject
{
private int _id;
public int Id {
get
{ return _id; }
set
{ _id = value; }
}
}
然後我重寫了查詢以使用_id私有字段而不是屬性。性能在91毫秒左右好得多。下面是該代碼:
private SimpleObject[] GetSimpleObjectUsingSodaAgainstAField(int[] matchingIds, IObjectContainer db)
{
SimpleObject[] returnValue = new SimpleObject[matchingIds.Length];
for (int counter = 0; counter < matchingIds.Length; counter++)
{
var query = db.Query();
query.Constrain(typeof(SimpleObject));
query.Descend("_id").Constrain(matchingIds[counter]);
IObjectSet queryResult = query.Execute();
if (queryResult.Count == 1)
returnValue[counter] = (SimpleObject)queryResult[0];
}
return returnValue;
}
只是爲了確保它是不是僥倖,我跑了試運行多次,收到了類似的結果。然後我又增加了60,000條記錄,共計90,000條,這是性能差異:
GetAll: 2450 ms
GetWithOriginalCode: 2694 ms
GetWithSODAandProperty: 75373 ms
GetWithSODAandField: 77 ms
希望有所幫助。我知道它並不能真正解釋爲什麼,但這可能有助於如何。此外,SODA字段查詢的代碼不會很難包裝成更通用的。
我注意到您發佈在db4o論壇中:http://developer.db4o.com/forums/57635/ShowThread.aspx。我添加了關於他們推薦的方法的評論。 – 2009-11-12 17:36:17