2010-05-16 31 views
2

我起草了2 ASP.NET應用程序使用LINQ。一個連接到MS SQL Server,另一個專有內存結構。 這兩個應用程序使用表3 int字段,有500 000記錄(內存結構是相同的SQL Server表)。使用的控件是常規的:GridViewObjectDataSource。 在應用程序中,我計算每個分頁點擊處理所需的平均時間。比較2 linq應用程序:意想不到的結果

  • LINQ + MS SQL應用程序需求0.1秒每頁更改。
  • LINQ +內存結構要求每頁改變0.8秒。

這是令人震驚的結果。爲什麼內存中的應用程序處理數據比使用硬盤驅動器的應用程序工作速度慢8倍?有人能告訴我爲什麼會發生這種情況嗎?

+0

您能否發佈您的查詢? – 2010-05-16 12:18:56

回答

4

主要因素可能是算法效率。 LINQ到對象與IEnumerable<T>輸入和輸出一起使用,輸入和輸出通常是按順序處理的,而數據庫可能具有會導致顯着提速的索引。

0

我能想到的至少有三個原因:

  • 指標
  • 緩存
  • 特殊的優化(如TOP N SORT)

指標

有許多類型的查詢運行速度非常快一個正確索引的數據庫,但是如果您遍歷內存中的列表,則會非常慢。例如,通過ID(主鍵)進行的查找在數據庫中幾乎是即時的,因爲結果存儲在具有非常小高度的B樹中。要在內存列表中找到相同的元素,需要掃描整個列表。

緩存

你的假設是,該數據庫總是命中磁盤。這並非總是如此。數據庫將嘗試儘可能多地在內存中保存數據,因此當您向數據請求數據時,它已經爲您準備好了答案。特別是它會在內存中保存常用索引,並且只在需要時纔打開磁盤。數據存儲在磁盤和內存中的方式也經過精心優化,以減少磁盤搜索和頁面丟失。

優化

即使沒有索引的數據庫,還知道很多竅門,可以加快速度。例如,如果你在SQL Server中的以下情況:

list.OrderBy(x => x.Value).Take(1) 

這將是幾乎瞬間如果在列表中的索引,但即使沒有該指數將使用名爲TOP N SORT了特別的優化,在線性時間運行。檢查查詢的執行計劃以查看是否正在使用此優化。請注意,這種優化不適用於LINQ to Objects。我們可以通過運行此代碼看到這一點:

Random random = new Random(); 
List<Foo> list = new List<Foo>(); 
for (int i = 0; i < 10000000; ++i) 
{ 
    list.Add(new Foo { Id = random.Next() }); 
} 

DateTime now = DateTime.UtcNow; 
Foo smallest = list.OrderBy(foo => foo.Id).First(); 
Console.WriteLine(DateTime.UtcNow - now); 

此代碼需要大約30秒的執行和執行時間比增長呈線性增加了更多的項目慢。更換與此查詢結果它取不到一秒:

int smallestId = list.Min(foo => foo.Id); 

這是因爲在LINQ到對象OrderBy是使用O(n log(n))算法來實現的,但Min使用O(n)算法。但是,在針對SQL Server執行時,這兩個查詢都將生成相同的SQL,並且都是線性時間 - O(n)

因此,在數據庫中運行諸如OrderBy(x => x.Something).Skip(50).Take(10)之類的分頁查詢會更快,因爲我們已經花費了更多精力確保其速度更快。畢竟,這種查詢的速度是數據庫的一個主要賣點。