2012-06-20 36 views
6

trong bộ nhớ tôi có một danh sách: người sử dụng Bộ sưu tập trong đó có khoảng 100K + hồ sơ của người sử dụng (tất cả đối tượng người dùng nạp đầy đủ từ cơ sở dữ liệu với các lĩnh vực như Bio, Tên, họ cuối cùng vv). Bộ sưu tập này được tìm nạp khi bắt đầu ứng dụng từ cơ sở dữ liệu và được lưu trong bộ nhớ.LINQ hiệu suất cho bộ sưu tập

Sau đó, tôi có mã như:

User cachedUser = users.FirstOrDefault(x => string.Equals(x.UserName, username, 
StringComparison.CurrentCultureIgnoreCase)); 

nào tôi sử dụng để lấy người dùng từ bộ sưu tập này. Nhưng bằng cách nào đó tôi nhận thấy rằng hoạt động này là cực kỳ chậm. Có một vấn đề hiệu suất trong khi sử dụng LINQ để truy vấn trong bộ sưu tập bộ nhớ của các đối tượng lớn? Thay vào đó, tôi có nên gọi cho DB mỗi khi tôi muốn có người dùng không?

+7

Bạn hiểu rằng 'FirstOrDefault' là O (n), phải không? Nếu bạn có một bộ sưu tập rất lớn, kiểm tra từng mục một sẽ mất một thời gian. (và dbs thường được lập chỉ mục) Có rất nhiều cách để tăng tốc độ này, không ít nhất là chỉ cần ném nó vào một từ điển. Có lý do nào bạn không làm điều đó không? –

+0

Tôi muốn bộ nhớ cache tất cả người dùng nghĩ rằng nó sẽ là tốt hơn cho lý do hiệu suất như GetUser() phương pháp đang được gọi trên hầu như mỗi trang của ứng dụng của tôi. Nếu tôi sử dụng một từ điển, nó sẽ nhanh hơn nhiều? Là từ điển O (1)? Hay tôi cần phải sắp xếp từ điển của tôi trước? –

+0

Bạn chỉ cần lưu bộ nhớ cache người dùng hiện tại? Bạn chỉ có thể sử dụng đối tượng 'Session' hoặc' Cache' được tích hợp sẵn cho điều đó. –

Trả lời

3

Nếu bạn muốn tối ưu hóa thời gian phản hồi của bạn và bạn có thể tạo ra một Dictionary<T,U> và tìm kiếm người dùng trong:

Dictionary<string, User> usersDictionary = new <Dictionary<string, User>(StringComparer.CurrentCultureIgnoreCase); 

    // After querying the users from the DB add them to the dictionary    
    usersDictionary.Add(user.UserName, user); 

    // Then when you need to retrieve a user 
    User retrieveUser = null; 
    usersDictionary.TryGetValue(username, out retrieveUser); 

Hy vọng rằng sẽ giúp!

+0

Bạn có thể có nghĩa là 'Từ điển mới (StringComparer.CurrentCultureIgnoreCase)' vì câu hỏi muốn trường hợp không nhạy cảm – adrianm

+0

Có điểm tốt, cảm ơn tôi sẽ cập nhật phản hồi của tôi. –

+1

Tôi không nghĩ rằng nên tải tất cả người dùng vào từ điển. Điều đó tốn rất nhiều thời gian và trí nhớ.Hơn nữa, bạn phải đồng bộ hóa quyền truy cập trong trường hợp bạn thay đổi dữ liệu. – slfan

3

truy vấn LINQ của bạn giống như bất kỳ kỹ thuật lặp khác (vòng lặp, tìm kiếm trong mảng) sẽ truy cập vào tất cả các hồ sơ duy nhất cho đến khi kỷ lục được yêu cầu được tìm thấy. Trong trường hợp xấu nhất có nghĩa là so sánh 100k. Để làm cho việc này nhanh hơn, bạn có các tùy chọn sau:

  1. sử dụng danh sách được sắp xếp hoặc từ điển: tìm kiếm nhị phân nhanh hơn rất nhiều. Sắp xếp dữ liệu khi lấy nó ra khỏi cơ sở dữ liệu bằng cách sử dụng ORDER BY
  2. sử dụng một DataSet. Nó giống như một cơ sở dữ liệu trong bộ nhớ cung cấp nhanh hơn tìm kiếm
  3. Để lại các dữ liệu trong cơ sở dữ liệu và thiết lập các chỉ số thích hợp cho việc truy cập nhanh hơn

Tôi đề nghị để sử dụng cơ sở dữ liệu do các nguyên nhân sau:

  • Đó là một sự lãng phí bộ nhớ để lưu trữ 100k bản ghi, mà bạn có thể không bao giờ sử dụng
  • Ngay sau khi bạn thay đổi dữ liệu của mình, bạn sẽ phải làm mới bộ nhớ cache của mình, có thể khá phức tạp
  • web applicati các tiện ích được đa luồng (mọi yêu cầu chạy trong chuỗi riêng của nó). Trong trường hợp bạn thay đổi dữ liệu, bạn sẽ phải đồng bộ hóa với các khóa.
  • một cơ sở dữ liệu có thể cache thường được gọi là dữ liệu
  • bạn phải viết mã ít hơn
  • bạn có một ứng dụng web không quốc tịch mà quy mô tốt hơn (trang trại web)
  • ứng dụng của bạn có thể có các dữ liệu khác, bạn không thể lưu trữ tất cả mọi thứ trong bộ nhớ
+0

vấn đề của tôi là với quá nhiều bản ghi ngay cả việc truy cập DB chậm. Vì vậy, tôi nghĩ lý do tại sao không bộ nhớ cache tất cả người dùng trong bộ nhớ như tôi đã sử dụng sự kiện để quản lý các đối tượng được lưu trữ khi người dùng cập nhật hồ sơ của mình. Không thể chúng tôi lập chỉ mục này trong bộ nhớ cache bằng cách nào đó? –

+3

Bạn sử dụng loại cơ sở dữ liệu nào? Bản ghi 100k không nhiều, khi đặt chỉ mục trên các hàng bạn đang tìm kiếm. Tôi sẽ không bao giờ lưu giữ nhiều bản ghi trong bộ nhớ trong một ứng dụng web. – slfan

+0

100K trong DB của chúng tôi có thể sớm đạt tới 1 triệu. Điểm là không có vấn đề gì RAM sẽ luôn luôn được nhanh hơn so với các tập tin dữ liệu vật lý. Vậy tại sao không có một số thuật toán tìm kiếm hiệu năng cao trong mã sử dụng bộ nhớ dựa trên RAM thay vì dựa vào DB? –

8

Tôi nghĩ rằng bạn có thể cần phải suy nghĩ lại về kiến ​​trúc của bạn dựa trên thông tin mà bạn đã cho chúng ta. Tận dụng cơ sở dữ liệu và để nó thực hiện công việc tìm kiếm cho bạn. Quan sát, đo lường và thực hiện các thay đổi cho phù hợp sau đó. Bạn có thể nhận ra rằng bạn đã tối ưu hóa toàn bộ mọi thứ.

0

Chênh lệch trong việc thực hiện tìm kiếm mà bạn nhận thấy là vì cơ sở dữ liệu là sử dụng lập chỉ mục để xác định vị trí các chuỗi trong cơ sở dữ liệu, nhưng bạn trong bộ nhớ bạn tìm kiếm đơn giản tất cả hồ sơ cho đến khi bạn tìm thấy một sự. Ngoài ra, cơ sở dữ liệu giữ một số băm cho chuỗi và tìm kiếm số băm này nhanh hơn rất nhiều và không thực sự so sánh chuỗi.

Dictionary<> cũng làm một chỉ mục, nhưng có sự chậm trễ để thêm dữ liệu, khi dữ liệu bắt đầu phát triển vì khi thêm dữ liệu, mỗi lần tìm kiếm vị trí đặt nó vào đúng điểm chỉ mục.

Ngoài ra bộ đệm ẩn cơ sở dữ liệu kết quả, nhiều bộ nhớ cache cơ sở dữ liệu cũng lập chỉ mục và tạo số liệu thống kê bổ sung giúp định vị nhanh những gì bạn đang tìm kiếm.

Tốt hơn là để cơ sở dữ liệu thực hiện tìm kiếm, ngoại trừ nếu bạn có thể thực hiện điều gì đó nhanh hơn cho các trường hợp tùy chỉnh bổ sung.

Các vấn đề liên quan