2010-07-27 22 views
12

Tôi hiện đang thực hiện một số nghiên cứu về việc sử dụng bộ nhớ db4o cho ứng dụng web của mình. Tôi khá hài lòng về cách thức hoạt động của db4o. Vì vậy, khi tôi đọc về phương pháp Code First, tôi thích là vì cách làm việc với EF4 Code First khá giống với làm việc với db4o: tạo các đối tượng miền của bạn (POCO), ném chúng vào db4o và không bao giờ nhìn lại.Tại sao mã EF4 Đầu tiên quá chậm khi lưu trữ các đối tượng?

Nhưng khi tôi thực hiện so sánh hiệu suất, EF 4 rất chậm. Và tôi không thể hiểu tại sao.

tôi sử dụng các đối tượng sau:

public class Recipe { private List _RecipePreparations; public int ID { get; set; } public String Name { get; set; } public String Description { get; set; } public List Tags { get; set; } public ICollection Preparations { get { return _RecipePreparations.AsReadOnly(); } }

public void AddPreparation(RecipePreparation preparation) 
    { 
     this._RecipePreparations.Add(preparation); 
    } 
} 

public class RecipePreparation { public String Tên {get; bộ; } chuỗi công khai Mô tả {get; bộ; } Xếp hạng công khai {get; bộ; } Danh sách công khai Các bước {get; bộ; } Thẻ danh sách công khai {get; bộ; } ID công khai {get; bộ; }}

Để kiểm tra việc thực hiện tôi mới lập một công thức, và thêm 50.000 RecipePrepations. Sau đó, tôi lưu trữ các đối tượng trong db4o như vậy:

IObjectContainer db = Db4oEmbedded.OpenFile(Db4oEmbedded.NewConfiguration(), @"RecipeDB.db4o"); 
db.Store(recipe1); 
db.Close(); 

này mất khoảng 13.000 (ms)

tôi lưu trữ những thứ với EF4 trong SQL Server 2008 (Express, địa phương) như thế này:

cookRecipes.Recipes.Add(recipe1); 
cookRecipes.SaveChanges(); 

Và điều đó mất 200.000 (mili giây)

Bây giờ làm thế nào trên trái đất là nhanh hơn DB4o 15 (!!!) nhanh hơn? Tôi có thiếu nút turbo bí mật cho EF4 không? Tôi thậm chí nghĩ rằng db4o có thể được thực hiện nhanh hơn? Vì tôi không khởi tạo tệp cơ sở dữ liệu, tôi chỉ cho phép nó phát triển động.

+1

tôi đoán là các chi phí của nhiều đơn chèn-báo cáo được thực hiện là phần lớn nhất của sự khác biệt. Có cách nào để hướng dẫn EF4 kết hợp các câu lệnh chèn để giảm chi phí trên không? –

+0

@Lasse: Có, có. EF thực hiện các đơn vị của mô hình công việc ra khỏi hộp - xem câu trả lời của tôi. –

+1

Tôi đã thực hiện một số hồ sơ với Visual Studio. Và cookRecipes.Recipes.Add (recipe1) chiếm khoảng 65% tổng thời gian để lưu trữ, và SaveChanges xấp xỉ 35% (duh ...;)). – Saab

Trả lời

3

Bạn có gọi SaveChanges()bên trong vòng lặp không? Không có thắc mắc nó chậm! Hãy thử làm điều này:

foreach(var recipe in The500000Recipes) 
{ 
    cookRecipes.Recipes.Add(recipe); 
} 
cookRecipes.SaveChanges(); 

EF hy vọng bạn thực hiện tất cả các những thay đổi mà bạn muốn, và sau đó gọi SaveChangeslần. Bằng cách đó, nó có thể tối ưu hóa giao tiếp cơ sở dữ liệu và sql để thực hiện các thay đổi giữa trạng thái mở và trạng thái lưu, bỏ qua tất cả các thay đổi mà bạn đã hoàn tác. (Ví dụ: thêm 50 000 bản ghi, sau đó xóa một nửa số bản ghi đó, sau đó nhấn SaveChanges sẽ chỉ thêm 25 000 bản ghi vào cơ sở dữ liệu. Bao giờ)

+0

Vòng lặp trước khi bất kỳ dữ liệu nào được lưu trữ trong db4o hoặc EF4/SQL. Vì vậy, tôi lần đầu tiên mới lên Recipe, sau đó trong một vòng lặp tôi thêm RecipePreparations. Vì vậy, bây giờ tôi có một Công thức, với 50.000 RecipePreparation gắn liền với nó. Sau đó, tôi lưu trữ điều này trong db4o hoặc EF4/SQL. Vì vậy, một db.store (recipe1) duy nhất trong db4o, và một cookRecipes.Recipes.Add (recipe1); cookRecipes.SaveChanges() trong EF4. – Saab

+0

DB4O đang lưu vào một tệp trên máy cục bộ của bạn phải không? Và EF4 phải mở một kết nối cơ sở dữ liệu cục bộ. Kết nối thường sẽ vẫn mở để nó là chi phí mỗi lần phát hành. Hãy thử thêm một dòng để lấy mục đầu tiên trong cơ sở dữ liệu trước vòng lặp thời gian của bạn để chèn để có được thời gian kết nối đó khỏi phương trình. – DamienG

1

EF trội hơn nhiều, nhưng tải hàng loạt không phải là một trong số chúng . Nếu bạn muốn tải hàng loạt hiệu suất cao, hãy thực hiện trực tiếp qua máy chủ DB sẽ nhanh hơn bất kỳ ORM nào. Nếu hạn chế hiệu suất duy nhất của ứng dụng của bạn là tải hàng loạt, thì có thể bạn không nên sử dụng EF.

+0

Sau đó, tôi có nghi ngờ về việc sử dụng EF. Khi ứng dụng của bạn dựa vào một mô hình rất phức tạp (các đối tượng miền) thì tôi thích cơ sở dữ liệu oo (như db4o). Nhưng khi dữ liệu chủ yếu là bảng, bạn sẽ sử dụng một cơ sở dữ liệu quan hệ truyền thống với, và tùy chọn một OR/M như EF. Nhưng như bạn nói EF không thành công khi bạn tải nặng/chèn/cập nhật. Vì vậy, những gì tôi đã sợ là thực sự đúng sự thật. EF4 chỉ là một tùy chọn khi thực hiện các hoạt động cơ sở dữ liệu rất nhẹ và bạn bị mắc kẹt khi sử dụng một cơ sở dữ liệu quan hệ. – Saab

+1

Một lần nữa, không chỉ EF, nhưng * bất kỳ * ORM sẽ chậm hơn các tính năng tải hàng loạt của máy chủ DB. EF có thể chậm hơn các ORM hỗ trợ chèn số lượng lớn, nhưng ngay cả những ORM cũng không nhanh bằng các API phát trực tuyến được sử dụng trên các tính năng tải hàng loạt dành riêng cho máy chủ DB. Tải hàng loạt là một trường hợp góc cho hầu hết các ứng dụng, nhưng nếu đó là bánh mì và bơ của bạn thì bạn nên làm tốt hơn để sử dụng một cái gì đó giống như SSIS hơn một ORM. –

+0

Tôi đồng ý rằng hầu hết các OR/M sẽ chậm hơn chỉ tải hàng loạt. Nhưng tôi phải không đồng ý rằng một OR/M cũng không thể sử dụng các tính năng tải hàng loạt của một cơ sở dữ liệu. Mã này rất dễ tạo. Nhưng tôi nghĩ có gì đó không ổn với EF4 Code First. Vì chỉ cần thêm đối tượng Công thức vào dbContext mất rất nhiều thời gian (130 giây). Lưu trữ trong cơ sở dữ liệu (dbContext.Recipes.SaveChanges) không phải là một con quỷ tốc độ, hoặc là 70 giây cho 50.001 hàng. Dịch thành 50.000/70 = 714 hàng/s. – Saab

1

Chỉ cần thêm vào các câu trả lời khác: db4o thường chạy trong khi xử lý, trong khi EF tóm tắt cơ sở dữ liệu ngoài quy trình (SQL). Tuy nhiên, db4o về cơ bản là đơn luồng.Vì vậy, trong khi nó có thể nhanh hơn cho ví dụ này với một yêu cầu, SQL sẽ xử lý đồng thời (nhiều truy vấn, nhiều người dùng) tốt hơn nhiều so với thiết lập cơ sở dữ liệu db4o mặc định.