2010-10-16 24 views
6

Tôi cần tìm nạp và hiển thị dữ liệu trên trang web có số lượng hồ sơ có thể khác nhau dựa trên bộ lọc từ khoảng 500 hồ sơ đến 1 triệu bản ghi.Điều gì sẽ là cách tốt nhất để tìm nạp khoảng một triệu bản ghi từ DB?

Việc lưu vào bộ nhớ đệm có được sử dụng ở đây không khi tôi nghĩ rằng triệu bản ghi trong bộ nhớ không phải là một suy nghĩ tốt. SqldataReader?

Phân trang là điều bắt buộc phải thực hiện tất nhiên. Hiển thị 1 triệu bản ghi là trường hợp xấu nhất (số All filter ngu ngốc trong trường hợp sử dụng!).

Tôi có nên sử dụng kiến ​​trúc được kết nối (SqlDataReader) hoặc kiến ​​trúc đã ngắt kết nối (DataSets) không?

+4

Tôi chỉ đang cố gắng tìm ra nếu có đủ giờ trong ngày để trang qua hàng triệu hàng dữ liệu. chúng ta hãy nói 40 hàng trên mỗi trang để 25.000 trang cần thiết, nói 1 phút duyệt mỗi trang sẽ là 25.000 phút hoặc khoảng 17 ngày - eeeek –

+3

Nó hoàn toàn không có ý nghĩa để hiển thị một triệu hồ sơ nếu bạn hỏi tôi. Kịch bản ở đây là gì? –

+0

Là một sang một bên, giả sử hồ sơ của bạn có trung bình 150 byte (đó là giống như một tên, một mô tả ngắn, một vài ints và một vài bools). 1 triệu bản ghi sẽ nhỏ hơn 150MB. Không thực sự quá nhiều để lưu trữ trong bộ nhớ cache. Tuy nhiên, cần lưu ý rằng máy chủ cơ sở dữ liệu của bạn (có thể là SQL Server) đã làm bộ nhớ đệm. Trong thực tế, nếu các truy vấn như vậy là phổ biến và bạn có rất nhiều bộ nhớ, tôi nghĩ rằng có thể toàn bộ bảng nằm trong bộ nhớ. – tster

Trả lời

10

Trước hết, hãy nghĩ về điều này như thế này: hiển thị 1 triệu bản ghi hoàn toàn không có ý nghĩa với bất kỳ người dùng nào. Vì vậy, bạn phải suy nghĩ về những gì người dùng mong đợi để xem. Có lẽ một bản tóm tắt ?! Có thể phân trang các bản ghi trong các trang có 25 hoặc 50 hoặc 100 bản ghi. Một trong những cách tiếp cận này sẽ không yêu cầu bạn giữ 1 bản ghi M tại một thời điểm trong bộ nhớ.

Ngoài ra, khi bạn chạy truy vấn đối với cơ sở dữ liệu SQL và sử dụng SqlDataReader bạn sẽ không nhận được tất cả bản ghi mà thay vào đó trình điều khiển SQL sẽ gửi truy vấn đến máy chủ SQL, máy chủ sẽ thực hiện truy vấn, tập hợp kết quả và tạo con trỏ chỉ chuyển tiếp trên máy chủ. Sau đó, trình điều khiển sẽ lấy một bản ghi tại một thời điểm, mỗi khi bạn gọi Đọc() trên SqlDataReader của bạn. Hành vi này rất giống nhau nếu bạn sử dụng LINQ to SQL trong đó sử dụng thực thi hoãn lại. Tập kết quả không được chuyển giao đầy đủ cho đến khi (hoặc trừ khi) bạn yêu cầu cụ thể từng hàng.

Vì vậy, truy vấn phân trang đơn giản sẽ thực hiện thủ thuật. Hoặc trong các trường hợp khác, một số loại báo cáo tóm tắt tổng hợp dữ liệu từ 1 triệu bản ghi này một hoặc hai trang dữ liệu có liên quan. Tất nhiên nếu bạn cần di chuyển qua lại giữa các trang, một số loại bộ nhớ đệm có thể có ý nghĩa nhưng một lần nữa, hãy nghĩ về nó: tần suất người dùng thực sự muốn duyệt qua 1 triệu bản ghi - có lẽ không bao giờ. Lưu ý cuối cùng, nếu bạn thực hiện phân trang - hãy đảm bảo rằng phương pháp bạn sử dụng để triển khai phân trang dựa trên máy chủ SQL gửi dữ liệu một trang tại một thời điểm và không đọc tất cả 1 triệu bản ghi vào ASP.NET và sau đó phân trang bản sao dữ liệu cục bộ bởi vì điều đó sẽ rất kém hiệu quả và chậm. Dưới đây là ví dụ về truy vấn SQL Server thực hiện phân trang: SO Question #109232

+0

Giải thích chi tiết tuyệt vời. Cảm ơn! Nhưng vẫn là một câu hỏi: Sẽ không có DataSets có sự giúp đỡ nào ở đây không? – Manish

+1

Một Số liệu hoạt động khác nhau. Trái ngược với SqlDataReader có hành vi chuyển tiếp, một DataSet phải mang tất cả dữ liệu từ máy chủ cục bộ trước khi hoạt động trên nó. Điều này làm cho nó dễ sử dụng hơn trong một số trường hợp nhưng nếu bạn truy vấn có thể trả về 1 triệu bản ghi, DatSets không phải là giải pháp. Cuối cùng, tất cả phụ thuộc vào truy vấn. –

1

Nếu máy chủ của bạn không thể lưu trữ 1 triệu bản ghi làm cách nào bạn nghĩ trình duyệt web của người dùng sẽ xử lý 1 triệu bản ghi đáng giá HTML?

xem xét phân trang (here is an example with 1 million records)

Cũng xem xét rằng người dùng không bao giờ muốn nhiều hơn khoảng 30 đến 50 hồ sơ. Bạn đang hiển thị chúng ở mức độ chi tiết quá thấp hoặc bạn cần lọc nhiều hơn.

+0

Liên kết đó thật tuyệt. Sắp xếp những gì tôi muốn. Nhưng nó sử dụng gì trong background..DataSets? Tôi thấy việc truy xuất khá nhanh. – Manish

+0

@Manish, nền là bất khả tri đối với lưới đó. Sử dụng bất kỳ ngôn ngữ nào bạn có thể kết nối với bất kỳ cơ sở dữ liệu nào. Sau đó, mẹo là viết các truy vấn SQL sử dụng các chỉ mục một cách chính xác sao cho các hàng trả về n-m là nhanh. – tster

3

Tôi đồng ý với phần còn lại của người trả lời. hiển thị 1 triệu bản ghi là lố bịch. Tuy nhiên, bạn có thể hiển thị các bản ghi X đầu tiên và trang qua.

Bí quyết là trong Stored Procedure làm lấy

ALTER PROCEDURE [dbo].[MyHugeTable_GetWithPaging] 
( 
     @StartRowIndex  int, 
     @MaximumRows  int 
) 

AS 
SET NOCOUNT ON 

Select 
    RowNum, 
    [UserName] 
From 
    (Select 
     [ID], 
     [UserName] 
     Row_Number() Over(Order By [ID] Desc) As RowNum 
     From dbo.[MyHugeTable] t) 
As DerivedTableName 
Where RowNum Between @StartRowIndex And (@StartRowIndex + @MaximumRows) 
+0

Thực ra DB là MS-SQL Server 2008. – Manish

+0

Yup, đó là những gì tôi sử dụng. –

+0

Đẹp! Hấp dẫn!! – Manish

0

Tôi sẽ đề nghị sử dụng truy vấn năng động với phân trang. do đó, khi bạn nhấp vào các bản ghi tìm nạp trang cụ thể chỉ cho các trang đó. Để lấy bản ghi từ cơ sở dữ liệu từ việc sử dụng phạm vi cụ thể sau truy vấn.

như thế này.

Create proc Test 

@take smallint, 
@skip smallint, 
@orderBy nvarchar(20), 
@subscriptionid smallint, 


as 

DECLARE @SQLQuery AS NVARCHAR(max) 

SET @SQLQuery=' Select ROW_NUMBER() OVER (ORDER BY P.ProductId desc) as RowNum,* from product" 

set @[email protected] + ' and Subscriptionid='+CONVERT(nvarchar, @subscriptionid) 

set @SQLQuery= ';WITH Results_CTE AS ('[email protected] 

    set @SQLQuery= @SQLQuery +') SELECT * FROM Results_CTE WHERE RowNum > '+CONVERT(nvarchar, @skip)+' AND RowNum <= '+CONVERT(nvarchar, @[email protected]) --//paging'; 
END 

EXECUTE sp_executesql @SQLQuery 
Các vấn đề liên quan