我有一個巨大的表,我需要通過一定的順序讀取和計算一些彙總統計信息。該表已經有正確順序的聚集索引,因此獲取記錄本身非常快。我正在嘗試使用LINQ to SQL來簡化我需要編寫的代碼。問題是我不想將所有對象加載到內存中,因爲DataContext似乎將它們放在了一邊 - 但試圖將它們分頁會導致可怕的性能問題。閱讀巨大的表的LINQ to SQL:運行內存VS慢分頁
這裏的擊穿。原始嘗試是這樣的:
var logs =
(from record in dataContext.someTable
where [index is appropriate]
select record);
foreach(linqEntity l in logs)
{
// Do stuff with data from l
}
這是相當快,並以良好的速度流,但問題是內存使用應用程序的繼續上升從未停止。我的猜測是,LINQ to SQL實體正在存儲在內存中,沒有正確處理。所以在閱讀Out of memory when creating a lot of objects C#後,我嘗試了以下方法。這似乎是常見的Skip
/Take
範例,許多人使用,以節省內存的附加功能。
注意_conn
預先創建的,併爲每個查詢創建臨時數據上下文,從而在相關聯的實體被垃圾收集。
int skipAmount = 0;
bool finished = false;
while (!finished)
{
// Trick to allow for automatic garbage collection while iterating through the DB
using (var tempDataContext = new MyDataContext(_conn) {CommandTimeout = 600})
{
var query =
(from record in tempDataContext.someTable
where [index is appropriate]
select record);
List<workerLog> logs = query.Skip(skipAmount).Take(BatchSize).ToList();
if (logs.Count == 0)
{
finished = true;
continue;
}
foreach(linqEntity l in logs)
{
// Do stuff with data from l
}
skipAmount += logs.Count;
}
}
現在我有理想的行爲,因爲我通過數據進行流式傳輸時內存使用率沒有增加。不過,我有一個差遠了問題:每個Skip
導致作爲基礎查詢,似乎確實導致服務器要經過所有的前幾頁的所有數據將數據加載越來越慢。在運行查詢時,每個頁面加載的時間越來越長,我可以判斷這是一個二次運算。這個問題已經出現在以下職位:
我似乎無法找到一種方法與LINQ做到這一點,讓我有被尋呼有限的內存使用數據,但每個頁面仍然在不斷的加載。有沒有辦法正確地做到這一點? 我的預感是,有可能是一些方法來告訴DataContext的明確忘記在上面的第一種方法的對象,但我不能找出如何做到這一點。
「我有一個巨大的表,我需要通過一定的順序讀取和計算一些彙總統計信息。」 - 在TSQL的服務器做吧....這就是它擅長! –
不,統計信息比這更復雜,並且不能用SQL查詢進行計算。數據需要按照一定的順序迭代,並且計算的東西在時間上是正確的,等等。 –
「不,統計信息比這更復雜,而且不能用SQL查詢進行計算」 - 真的嗎?是否可以舉一個完整的例子? –