2012-12-18 94 views
5

我有一張200,000記錄的表格,其中我只使用.Take()獲得前10名,但需要大約10秒才能獲取數據。Linq to entities很慢。使用.Take()方法

我的問題是:.Take()方法是從數據庫中獲取所有數據並篩選客戶端的前10位?

這裏是我的代碼:

mylist = (from mytable in db.spdata().OrderByDescending(f => f.Weight) 
            group feed by mytable.id into g 
            select g.FirstOrDefault()).Take(10).ToList(); 

spdata()是從存儲過程的函數導入。

感謝

+7

如果你想知道它違背了什麼數據庫,你應該勾廓線直到您的數據庫並檢查日誌,這是瞭解最佳方式。 – Chris

+1

如果spdata()返回200,000,那麼是,它會在客戶端執行它。 –

+0

除了Chris的方法,你也可以嘗試Linqpad並在編寫查詢之後切換到SQL視圖以查看生成的SQL,或者放置一個斷點(使用此方法http://stackoverflow.com/questions/1412863/how -do-i-view-the-the-the-the-the-the-entity-framework)來查看程序執行時產生的內容。 –

回答

8

存儲過程可能會向客戶端返回很多數據,這很慢。您無法將查詢遠程存儲到存儲區。這將可能使用視圖或表值函數。

在查詢中無法使用存儲過程。你只能自己執行它。

您的意圖可能是在服務器上執行Take(10)。爲了工作,你需要切換到內聯查詢,視圖或TVF。

6

擴展方法Take獲取所有從數據庫中的結果。這不是Take的工作原理。

但是,您的db.spdata()調用可能會獲取所有行。

1

我不是100%肯定,但我記得,當你調用使用EF的DataContext的SP你得到一個IEnumerable結果...

有一對夫婦的是優化的性能:

  • 傳遞搜索標準S作爲SP PARAMS並執行過濾在存儲過程中。

或者,如果你有在你不聲明任何變量,並在那裏你只是加入一些表則SP一個很簡單的查詢:

  • 創建索引視圖,其中指定查詢你需要並調用Take方法。
    這會給你什麼?您可以映射到創建的視圖,EF現在將返回IQueryable結果而不是IEnumerable。這將優化SQL命令和而接收的所有數據,然後取好需要將形成,僅僅檢索10種元素的SQL命令的10個元素。

我也建議你看看IEnumerable和IQueryable之間有什麼區別。

0

它的確如此,因爲您在分組之前對數據進行排序,這在SQL中是無法做到的。

你應該使用聚合從每個組獲得最高的權重,然後進行排序的權重,以獲得最大的十:

mylist = (
    from mytable in db.spdata() 
    group feed by mytable.id into g 
    select g.Max(f => f.Weight) 
).OrderByDescending(w => w).Take(10).ToList(); 
+0

它給出了一個錯誤錯誤「名爲'g'的局部變量不能在此範圍內聲明,因爲它會給'g'賦予不同的含義,'g'已經在'父'或'當前'範圍內用於表示其他內容」 –

+0

@AliIssa:對,它必須是一個不同的變量。我改變了它。 – Guffa