2009-03-26 21 views
16

Thời gian thực hiện bên dưới là 30 giây lần đầu tiên và 25 giây vào lần tiếp theo tôi thực thi cùng một bộ mã. Khi xem trong SQL Profiler, tôi ngay lập tức nhìn thấy một đăng nhập, sau đó nó chỉ ngồi đó trong khoảng 30 giây. Sau đó, ngay khi câu lệnh chọn được chạy, ứng dụng sẽ hoàn thành lệnh ToList. Khi tôi chạy truy vấn được tạo ra từ Management Studio, truy vấn cơ sở dữ liệu chỉ mất khoảng 400ms. Nó trả về 14 hàng và 350 cột. Có vẻ như thời gian cần phải chuyển đổi kết quả cơ sở dữ liệu sang các thực thể là quá nhỏ, nó không đáng chú ý.Tại sao Khung thực thể mất 30 giây để tải bản ghi khi truy vấn được tạo chỉ mất 1/2 giây?

Vậy điều gì sẽ xảy ra trong 30 giây trước khi thực hiện cuộc gọi cơ sở dữ liệu?

Nếu khung thực thể chậm, chúng tôi không thể sử dụng nó. Có điều gì tôi đang làm sai hay điều gì đó tôi có thể thay đổi để tăng tốc độ này một cách đáng kể?

UPDATE: Được rồi, nếu tôi sử dụng một truy vấn biên soạn, lần đầu tiên nó mất 30 giây, và lần thứ hai phải mất 1/4 của một giây. Tôi có thể làm gì để tăng tốc cuộc gọi đầu tiên không?

using (EntitiesContext context = new EntitiesContext()) 
{ 
    Stopwatch sw = new Stopwatch(); 
    sw.Start(); 
    var groupQuery = (from g in context.Groups.Include("DealContract") 
        .Include("DealContract.Contracts") 
        .Include("DealContract.Contracts.AdvertiserAccountType1") 
        .Include("DealContract.Contracts.ContractItemDetails") 
        .Include("DealContract.Contracts.Brands") 
        .Include("DealContract.Contracts.Agencies") 
        .Include("DealContract.Contracts.AdvertiserAccountType2") 
        .Include("DealContract.Contracts.ContractProductLinks.Products") 
        .Include("DealContract.Contracts.ContractPersonnelLinks") 
        .Include("DealContract.Contracts.ContractSpotOrderTypes") 
        .Include("DealContract.Contracts.Advertisers") 
       where g.GroupKey == 6 
       select g).OfType<Deal>(); 
    sw.Stop(); 
    var queryTime = sw.Elapsed; 
    sw.Reset(); 
    sw.Start(); 
    var groups = groupQuery.ToList(); 
    sw.Stop(); 
    var executeTime = sw.Elapsed; 
} 

Trả lời

12

Tôi gặp sự cố tương tự này, truy vấn của tôi mất 40 giây.

Tôi đã tìm thấy sự cố với các chức năng .Include("table_name"). Càng có nhiều những thứ tôi có, thì càng tệ hơn.Thay vào đó, tôi đã thay đổi mã của mình thành Lazy Load tất cả dữ liệu tôi cần ngay sau khi truy vấn, điều này đã làm giảm tổng thời gian xuống còn khoảng 1,5 giây từ 40 giây. Theo như tôi biết, điều này hoàn thành chính xác điều tương tự.

Vì vậy, đối mã của bạn nó sẽ là một cái gì đó như thế này:

var groupQuery = (from g in context.Groups 
      where g.GroupKey == 6 
      select g).OfType<Deal>(); 

var groups = groupQuery.ToList(); 

foreach (var g in groups) 
{ 
    // Assuming Dealcontract is an Object, not a Collection of Objects 
    g.DealContractReference.Load(); 
    if (g.DealContract != null) 
    { 
     foreach (var d in g.DealContract) 
     { 
      // If the Reference is to a collection, you can just to a Straight ".Load" 
      // if it is an object, you call ".Load" on the refence instead like with "g.DealContractReference" above 
      d.Contracts.Load(); 
      foreach (var c in d.Contracts) 
      { 
       c.AdvertiserAccountType1Reference.Load(); 
       // etc.... 
      } 
     } 
    } 
} 

Ngẫu nhiên, nếu bạn đã thêm dòng mã này trên các truy vấn trong mã hiện tại của bạn, nó sẽ gõ thời gian xuống còn khoảng 4 -5 giây (vẫn còn quá ling trong lựa chọn của tôi) Từ những gì tôi hiểu, tùy chọn MergeOption.NoTracking vô hiệu hóa rất nhiều các chi phí theo dõi để cập nhật và chèn thứ trở lại vào cơ sở dữ liệu:

context.groups.MergeOption = MergeOption.NoTracking; 
+3

Điều này dường như rất dễ nhìn. Làm cho nhiều yêu cầu SQL và tải cùng một số đối tượng nhanh hơn làm một yêu cầu sql? – toxaq

+0

Chris bạn dường như biết rất nhiều về .include bạn có thể vui lòng xem bài đăng của tôi http://stackoverflow.com/questions/10320174/speed-up-return-of-linq-entity-result –

+0

@bugz - Tôi đã nhìn. Tôi xin lỗi, tôi không biết. Tôi nên lưu ý rằng cuối cùng tôi đã rất không hài lòng với ASP.net và khung thực thể. Mọi thứ tôi đã làm mất quá nhiều thời gian. Tôi hiện đang viết lại toàn bộ ứng dụng đó trong công cụ ứng dụng của google. –

4

Đó là do Bao gồm. Tôi đoán là bạn đang háo hức tải rất nhiều vật thể vào bộ nhớ. Phải mất nhiều thời gian để xây dựng các đối tượng C# tương ứng với các thực thể db của bạn.

Đề xuất của tôi cho bạn là cố gắng chỉ tải xuống dữ liệu bạn cần.

+0

Lazy Loading wouldnt giúp đỡ bởi vì chúng ta cần tất cả của các đối tượng được bao gồm. Nó thực sự chỉ trả về tổng cộng 40 đối tượng (1 Deal, 3 DealContracts, 3 Contracts, 3 contractitemdetails trên mỗi hợp đồng, và 1 của mỗi tài sản khác trên mỗi hợp đồng), vì vậy tôi không nghĩ rằng nó sẽ là quá chuyên sâu ...? – NotDan

+0

Tôi không đồng ý rằng cần tất cả các đối tượng có nghĩa là tải chậm sẽ không giúp ích gì. Xem câu trả lời của tôi vì lý do. Đôi khi, thực hiện truy vấn đơn giản hơn sẽ nhanh hơn và sau đó cho phép các chi tiết với các truy vấn đơn giản khác. –

0

EF mất một lúc để khởi động. Nó cần xây dựng siêu dữ liệu từ xml và có thể tạo ra các đối tượng được sử dụng để lập bản đồ. Vì vậy, phải mất một vài giây để bắt đầu, tôi không nghĩ rằng có một cách để có được xung quanh đó, ngoại trừ không bao giờ khởi động lại chương trình của bạn.

+2

Thực sự, cần 30 giây để khởi động? Điều đó có vẻ quá mức. – billb

+0

Tôi đã không thực sự sử dụng nó với bất kỳ mô hình phức tạp nào, và mất khoảng 5 giây để khởi động phần lớn thời gian. Các đối tượng của bạn trông phức tạp hơn nhiều so với những đối tượng tôi có. Thử thực hiện truy vấn nhỏ hơn và xem mất bao lâu. – AndreasN

+0

Thêm truy vấn đơn giản (1 bản ghi, không bao gồm) trước khi truy vấn phức tạp tiết kiệm 2 giây. Vì vậy, có vẻ như EF mất 2 giây để khởi động. Vẫn còn mất 28 giây cho truy vấn phức tạp đầu tiên quá dài. – NotDan

2

Cách duy nhất để làm cho việc biên dịch ban đầu truy vấn nhanh hơn mà tôi biết là làm cho truy vấn ít phức tạp hơn. Tài liệu MSDN trên performance considerations for the Entity FrameworkCompiled Queries không cho biết có cách nào để lưu truy vấn được biên dịch để sử dụng trong phiên thực thi ứng dụng khác.

Tôi sẽ thêm rằng chúng tôi nhận thấy rằng có nhiều Bao gồm có thể thực hiện truy vấn chậm hơn so với việc có ít hơn Bao gồm và thực hiện nhiều Tải trên các thực thể liên quan sau này. Một số thử nghiệm và lỗi là cần thiết để tìm phương tiện phù hợp.

Tuy nhiên, tôi phải hỏi xem bạn có thực sự cần mọi tài sản của mọi pháp nhân mà bạn đang đưa vào đây hay không. Dường như với tôi rằng có một số lượng lớn các loại thực thể khác nhau trong truy vấn này, vì vậy việc thực hiện chúng có thể khá tốn kém. Nếu bạn chỉ đang cố gắng để có được kết quả dạng bảng mà bạn không có ý định cập nhật, hãy dự báo số lượng trường (tương đối) ít hơn mà bạn thực sự cần vào loại căn hộ, ẩn danh sẽ nhanh hơn đáng kể vì nhiều lý do khác nhau. Ngoài ra, điều này giải phóng bạn khỏi phải lo lắng về việc tải dữ liệu, tải xuống/tải, v.v.

Bạn chắc chắn có thể tăng tốc độ phát ban đầu bằng cách biên dịch trước chế độ xem thực thể. Có documentation on MSDN for this. Nhưng kể từ khi bạn trả chi phí đó tại thời điểm truy vấn đầu tiên được thực hiện, kiểm tra của bạn với một truy vấn đơn giản cho thấy rằng điều này đang chạy trong khu phố của 2 giây cho bạn. Thật tuyệt khi nói rằng 2 giây, nhưng nó sẽ không cứu được gì khác.

+0

Unfortunatlly, tôi thực sự cần tất cả các thuộc tính trên tất cả các đối tượng. – NotDan

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