我能想到的至少有三個原因:
指標
有許多類型的查詢運行速度非常快一個正確索引的數據庫,但是如果您遍歷內存中的列表,則會非常慢。例如,通過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)
之類的分頁查詢會更快,因爲我們已經花費了更多精力確保其速度更快。畢竟,這種查詢的速度是數據庫的一個主要賣點。
您能否發佈您的查詢? – 2010-05-16 12:18:56