Tôi có một bảng lớn mà tôi cần đọc qua một thứ tự nhất định và tính toán một số thống kê tổng hợp. Bảng đã có một chỉ số nhóm cho đúng thứ tự sao cho bản thân các bản ghi là khá nhanh. Tôi đang cố gắng sử dụng LINQ to SQL để đơn giản hóa mã mà tôi cần phải viết. Vấn đề là tôi không muốn tải tất cả các đối tượng vào bộ nhớ, vì DataContext dường như giữ chúng xung quanh - nhưng cố gắng để trang chúng kết quả trong các vấn đề hiệu suất khủng khiếp.Đọc bảng lớn với LINQ to SQL: Hết bộ nhớ và phân trang chậm
Đây là bảng phân tích. Nỗ lực ban đầu là:
var logs =
(from record in dataContext.someTable
where [index is appropriate]
select record);
foreach(linqEntity l in logs)
{
// Do stuff with data from l
}
Điều này là khá nhanh và luồng ở mức tốt, nhưng vấn đề là việc sử dụng bộ nhớ của ứng dụng liên tục không ngừng. Tôi đoán là các thực thể LINQ to SQL đang được lưu trữ trong bộ nhớ và không được xử lý đúng cách. Vì vậy, sau khi đọc Out of memory when creating a lot of objects C#, tôi đã thử cách tiếp cận sau. Đây có vẻ là mô hình phổ biến của Skip
/Take
mà nhiều người sử dụng, với tính năng tiết kiệm bộ nhớ bổ sung.
Lưu ý rằng _conn
được tạo trước và ngữ cảnh dữ liệu tạm thời được tạo cho mỗi truy vấn, dẫn đến các thực thể liên quan bị thu gom rác.
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;
}
}
Bây giờ tôi có hành vi mong muốn rằng việc sử dụng bộ nhớ không tăng chút nào khi tôi đang truyền trực tuyến dữ liệu. Tuy nhiên, tôi có một vấn đề tồi tệ hơn: mỗi Skip
đang làm cho dữ liệu tải ngày càng chậm vì truy vấn cơ bản dường như thực sự khiến máy chủ phải trải qua tất cả dữ liệu cho tất cả các trang trước đó. Trong khi chạy truy vấn mỗi trang mất nhiều thời gian hơn và lâu hơn để tải và tôi có thể nói rằng điều này đang chuyển thành hoạt động bậc hai. Vấn đề này đã xuất hiện trong các bài viết sau:
tôi dường như không thể tìm thấy một cách để làm điều này với LINQ cho phép tôi có sử dụng bộ nhớ hạn chế bởi phân trang dữ liệu, nhưng vẫn có tải trang mỗi lần liên tục. Có cách nào để làm điều này đúng không? Linh cảm của tôi là có thể có một số cách để báo cho DataContext biết rõ ràng về đối tượng trong cách tiếp cận đầu tiên ở trên, nhưng tôi không thể tìm ra cách để làm điều đó.
"Tôi có một bảng lớn mà tôi cần phải đọc qua một thứ tự nhất định và tính toán một số thống kê tổng hợp." - Làm điều đó tại máy chủ trong TSQL .... Đó là những gì nó là tốt! –
Không, các số liệu thống kê phức tạp hơn và không thể tính toán được với các truy vấn SQL. Dữ liệu cần được lặp lại thông qua một thứ tự nhất định và những thứ được tính toán đúng thời gian, v.v. –
"Không, số liệu thống kê phức tạp hơn và không thể tính toán được với các truy vấn SQL" - thực sự? Có thể đưa ra một ví dụ đầy đủ không? –