2011-02-08 43 views
19

Tôi có một bảng:Khi nào tôi nên sử dụng một CompiledQuery?

-- Tag 

ID | Name 
----------- 
1 | c# 
2 | linq 
3 | entity-framework 

Tôi có một lớp học mà sẽ có các phương pháp sau:

IEnumerable<Tag> GetAll(); 
IEnumerable<Tag> GetByName(); 

Tôi có nên sử dụng một truy vấn biên soạn trong trường hợp này?

static readonly Func<Entities, IEnumerable<Tag>> AllTags = 
    CompiledQuery.Compile<Entities, IEnumerable<Tag>> 
    (
     e => e.Tags 
    ); 

Sau đó, phương pháp GetByName của tôi sẽ là:

IEnumerable<Tag> GetByName(string name) 
{ 
    using (var db = new Entities()) 
    { 
     return AllTags(db).Where(t => t.Name.Contains(name)).ToList(); 
    } 
} 

nào tạo ra một SELECT ID, Name FROM Tag và thực hiện Where trên mã. Hoặc tôi có nên tránh CompiledQuery trong trường hợp này không?

Về cơ bản, tôi muốn biết khi nào nên sử dụng các truy vấn được biên dịch. Ngoài ra, trên một trang web họ được biên dịch chỉ một lần cho toàn bộ ứng dụng?

+0

Ví dụ bạn đưa ra sẽ thất bại khi chạy (bạn phải chuyển ngữ cảnh, và bạn không thể sử dụng 'Func <>' không có 'Expression <>'. Ngoài ra, tiếp tục soạn truy vấn ('Where (t =) > ... ')" decompiles "kết quả, nhưng câu hỏi là hợp lệ –

+1

Trong .net 4.5 nó sẽ được thực hiện tự động.Xem" Entity Framework 5: Kiểm soát biên dịch truy vấn tự động "http://blogs.msdn.com/ b/stuartleeks/lưu trữ/2012/06/12/tổ chức-khuôn khổ-5-kiểm soát-tự động-truy vấn-compilation.aspx) –

Trả lời

26

Bạn nên sử dụng một CompiledQuery khi tất cả những điều sau đây là đúng:

  • Truy vấn sẽ được thực hiện nhiều hơn một lần, chỉ khác nhau bởi các giá trị tham số.
  • Truy vấn là đủ phức tạp mà chi phí thẩm định biểu và xem thế hệ là "đáng kể" (thử và sai)
  • Bạn không sử dụng một tính năng LINQ như IEnumerable<T>.Contains() mà sẽ không làm việc với CompiledQuery.
  • Bạn đã đơn giản hóa truy vấn, mang lại lợi ích hiệu suất lớn hơn, khi có thể.
  • Bạn không có ý định tiếp tục soạn kết quả truy vấn (ví dụ: hạn chế hoặc dự án), có tác dụng "giải mã" nó.

CompiledQuery hoạt động lần đầu tiên khi truy vấn được thực thi. Nó không mang lại lợi ích cho việc thực hiện đầu tiên. Giống như bất kỳ điều chỉnh hiệu suất nào, thường tránh nó cho đến khi bạn chắc chắn rằng mình đang sửa một điểm phát sóng hiệu năng thực tế.

2012 Cập nhật: EF 5 sẽ tự động thực hiện việc này (xem "Entity Framework 5: Controlling automatic query compilation"). Vì vậy, thêm "Bạn không sử dụng EF 5" vào danh sách trên.

1

truy vấn được biên dịch hữu ích hơn với truy vấn LINQ với cây biểu thức lớn cho biết các truy vấn phức tạp để đạt được hiệu suất trên cây biểu thức xây dựng lặp đi lặp lại trong khi sử dụng lại truy vấn. trong trường hợp của bạn tôi đoán nó sẽ tiết kiệm được rất ít thời gian.

+0

'CHỌN ID, Tên TỪ Thẻ' so với' CHỌN ID, TỪ TÊN Thẻ WHERE Tên THÍCH '% tên% ''trên bảng hàng 1M, truy vấn được biên dịch sẽ đạt được hiệu suất thực hiện lựa chọn đầu tiên và sau đó lọc kết quả trên mã? – BrunoLM

+0

không hề, bạn nên lọc các bản ghi trên cấp DB chứ không phải trên mã. sai lầm để lọc mã. Truy vấn được biên dịch chỉ có nghĩa là điểm kinh nghiệm cây ression được biên soạn trước. truy vấn thứ hai là cách để đi –

0

Truy vấn được biên dịch cung cấp cải thiện hiệu suất nhưng không lớn. Nếu bạn có các truy vấn phức tạp, tôi muốn đi với một thủ tục lưu sẵn hoặc một khung nhìn, nếu có thể; cho phép cơ sở dữ liệu làm điều đó có thể là một cách tiếp cận tốt hơn.

+1

Các thử nghiệm của chúng tôi cho thấy rằng nếu bạn sử dụng lại truy vấn, nó có thể tăng lên đáng kể chậm trễ đáng kể do thời gian biên dịch. Đặc biệt nếu bạn có nhiều truy vấn khác nhau. –

0

Truy vấn biên dịch được biên dịch khi ứng dụng được biên dịch và mỗi khi bạn sử dụng lại truy vấn thường xuyên hoặc phức tạp, bạn chắc chắn nên thử các truy vấn được biên dịch để thực hiện nhanh hơn.

Nhưng tôi sẽ không cho nó trên tất cả các truy vấn vì nó là một ít mã hơn để viết và cho các truy vấn đơn giản nó có thể không đáng giá. Nhưng đối với hiệu suất tối đa, bạn cũng nên đánh giá các thủ tục lưu trữ khi bạn thực hiện tất cả quá trình xử lý trên máy chủ cơ sở dữ liệu, ngay cả khi LINQ cố gắng đẩy nhiều công việc tới db càng tốt. Nhanh hơn.

+4

Không, 'CompiledQuery' được biên dịch trong thời gian chạy, ngay trước lần thực hiện đầu tiên. –

6

Truy vấn được biên dịch giúp bạn tiết kiệm thời gian, chi phí sẽ được sử dụng để tạo cây biểu thức. Nếu truy vấn được sử dụng thường xuyên và bạn sẽ lưu truy vấn được biên dịch, bạn chắc chắn nên sử dụng nó. Tôi đã có nhiều trường hợp khi phân tích cú pháp truy vấn mất nhiều thời gian hơn so với chuyến đi vòng thực tế đến cơ sở dữ liệu.

Trong trường hợp của bạn, nếu bạn chắc chắn rằng nó sẽ tạo ra SELECT ID, Name FROM Tag mà không có trường hợp WHERE (mà tôi nghi ngờ, như chức năng AllQueries của bạn nên quay trở lại IQueryable và truy vấn thực tế nên chỉ được thực hiện sau khi gọi ToList) - bạn không nên sử dụng nó.

Như ai đó đã đề cập, trên bảng lớn hơn SELECT * FROM [someBigTable] sẽ mất rất nhiều thời gian và bạn sẽ dành nhiều thời gian lọc hơn ở phía khách hàng. Vì vậy, bạn nên chắc chắn rằng bộ lọc của bạn được thực hiện trên phía cơ sở dữ liệu, không có vấn đề nếu bạn đang sử dụng các truy vấn được biên dịch hay không.

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