2010-09-21 32 views
9

Trong dự án của tôi, tôi đang sử dụng EntityFramework 4 để làm việc với dữ liệu. Tôi đã tìm thấy các vấn đề hiệu suất khủng khiếp với một truy vấn đơn giản. Khi tôi nhìn vào hồ sơ trên một truy vấn sql, được tạo ra bởi EF4, tôi đã bị sốc.Truy vấn LINQ trong khung thực thể 4. Hiệu suất khủng khiếp

Tôi có một số bảng trong mô hình dữ liệu thực thể của tôi:

Data Model

Nó trông khá đơn giản. Tôi đang cố gắng chọn tất cả các mục sản phẩm từ danh mục được chỉ định với tất cả các thuộc tính điều hướng có liên quan.

tôi đã viết truy vấn LINQ này:

ObjectSet<ProductItem> objectSet = ...; 
int categoryId = ...; 

var res = from pi in objectSet.Include("Product").Include("Inventory").Include("Inventory.Storage") 
where pi.Product.CategoryId == categoryId 
select pi; 

EF tạo truy vấn sql này:

SELECT [Project1].[pintId1]   AS [pintId], 
[Project1].[pintId]   AS [pintId1], 
[Project1].[intProductId]  AS [intProductId], 
[Project1].[nvcSupplier]  AS [nvcSupplier], 
[Project1].[ nvcArticle]  AS [ nvcArticle], 
[Project1].[nvcBarcode]  AS [nvcBarcode], 
[Project1].[bIsActive]  AS [bIsActive], 
[Project1].[dtDeleted]  AS [dtDeleted], 
[Project1].[pintId2]   AS [pintId2], 
[Project1].[nvcName]   AS [nvcName], 
[Project1].[intCategoryId] AS [intCategoryId], 
[Project1].[ncProductType] AS [ncProductType], 
[Project1].[C1]    AS [C1], 
[Project1].[pintId3]   AS [pintId3], 
[Project1].[intProductItemId] AS [intProductItemId], 
[Project1].[intStorageId]  AS [intStorageId], 
[Project1].[dAmount]   AS [dAmount], 
[Project1].[mPrice]   AS [mPrice], 
[Project1].[dtModified]  AS [dtModified], 
[Project1].[pintId4]   AS [pintId4], 
[Project1].[nvcName1]   AS [nvcName1], 
[Project1].[bIsDefault]  AS [bIsDefault] 
FROM  (SELECT [Extent1].[pintId]   AS [pintId], 
[Extent1].[intProductId] AS [intProductId], 
[Extent1].[nvcSupplier] AS [nvcSupplier], 
[Extent1].[ nvcArticle] AS [ nvcArticle], 
[Extent1].[nvcBarcode]  AS [nvcBarcode], 
[Extent1].[bIsActive]  AS [bIsActive], 
[Extent1].[dtDeleted]  AS [dtDeleted], 
[Extent2].[pintId]   AS [pintId1], 
[Extent3].[pintId]   AS [pintId2], 
[Extent3].[nvcName]  AS [nvcName], 
[Extent3].[intCategoryId] AS [intCategoryId], 
[Extent3].[ncProductType] AS [ncProductType], 
[Join3].[pintId1]   AS [pintId3], 
[Join3].[intProductItemId] AS [intProductItemId], 
[Join3].[intStorageId]  AS [intStorageId], 
[Join3].[dAmount]   AS [dAmount], 
[Join3].[mPrice]   AS [mPrice], 
[Join3].[dtModified]  AS [dtModified], 
[Join3].[pintId2]   AS [pintId4], 
[Join3].[nvcName]   AS [nvcName1], 
[Join3].[bIsDefault]  AS [bIsDefault], 
CASE 
WHEN ([Join3].[pintId1] IS NULL) THEN CAST(NULL AS int) 
ELSE 1 
END AS [C1] 
FROM [ProductItem] AS [Extent1] 
INNER JOIN [Product] AS [Extent2] 
ON [Extent1].[intProductId] = [Extent2].[pintId] 
LEFT OUTER JOIN [Product] AS [Extent3] 
ON [Extent1].[intProductId] = [Extent3].[pintId] 
LEFT OUTER JOIN (SELECT [Extent4].[pintId]   AS [pintId1], 
[Extent4].[intProductItemId] AS [intProductItemId], 
[Extent4].[intStorageId]  AS [intStorageId], 
[Extent4].[dAmount]   AS [dAmount], 
[Extent4].[mPrice]   AS [mPrice], 
[Extent4].[dtModified]  AS [dtModified], 
[Extent5].[pintId]   AS [pintId2], 
[Extent5].[nvcName]   AS [nvcName], 
[Extent5].[bIsDefault]  AS [bIsDefault] 
FROM [Inventory] AS [Extent4] 
INNER JOIN [Storage] AS [Extent5] 
ON [Extent4].[intStorageId] = [Extent5].[pintId]) AS [Join3] 
ON [Extent1].[pintId] = [Join3].[intProductItemId] 
WHERE [Extent2].[intCategoryId] = 8 /* @p__linq__0 */) AS [Project1] 
ORDER BY [Project1].[pintId1] ASC, 
[Project1].[pintId] ASC, 
[Project1].[pintId2] ASC, 
[Project1].[C1] ASC 

Đối với 7000 bản ghi trong cơ sở dữ liệu và ~ 1000 kỷ lục trong thể loại nào đó của truy vấn này thời gian thực hiện id khoảng 10 giây . Nó không phải là đáng ngạc nhiên nếu xem xét điều này:

FROM [ProductItem] AS [Extent1] 
INNER JOIN [Product] AS [Extent2] 
ON [Extent1].[intProductId] = [Extent2].[pintId] 
LEFT OUTER JOIN [Product] AS [Extent3] 
ON [Extent1].[intProductId] = [Extent3].[pintId] 
***LEFT OUTER JOIN (SELECT ....*** 

Nested chọn trong tham gia ... Horrible ... Tôi đã cố gắng để thay đổi LINQ truy vấn, nhưng tôi nhận được cùng một truy vấn SQL outputted.

Một giải pháp sử dụng thủ tục lưu sẵn không được chấp nhận đối với tôi, vì tôi đang sử dụng cơ sở dữ liệu SQL Compact.

+3

Tiếng Anh của bạn không phải là xấu :) Câu hỏi được tạo hình quá. +1 – Aren

+1

Bạn có thể sử dụng http://imgur.com/ để chia sẻ hình ảnh. – Steven

+2

Có gì với Bao gồm? Tại sao không chỉ _from pi trong objectSet nơi pi.Product.CategoryId == categoryId chọn pi_? –

Trả lời

7

Bạn đang làm Include("Product").Include("Inventory").Include("Inventory.Storage") và bạn đang tự hỏi tại sao quá nhiều bản ghi được tìm nạp và tại sao lại thấy một truy vấn SQL lớn như vậy? Vui lòng đảm bảo bạn hiểu phương thức Include là gì. Nếu bạn muốn có một truy vấn đơn giản hơn, hãy sử dụng sau đây:

var res = 
    from pi in objectSet 
    where pi.Product.CategoryId == categoryId 
    select pi; 

Xin lưu ý tuy nhiên điều này sẽ có thể tải Products, InventoriesStorages uể oải, mà có thể gây ra nhiều truy vấn nhiều hơn để được gửi đi khi bạn duyệt qua những bộ sưu tập phụ .

+0

+1 điểm tốt - với Sản phẩm: ProductItem (1: *) và ProductItem: Khoảng không quảng cáo (1: *), một Sản phẩm sẽ tải toàn bộ rất nhiều dữ liệu phụ (có thể không cần thiết) .... không có thắc mắc nó chậm ... –

0

Tôi đang nghĩ vấn đề là với bộ sưu tập Khoảng không quảng cáo trong phần tử Bộ nhớ. Truy vấn của bạn sẽ giới hạn các mục Sản phẩm, Sản phẩm và Hàng tồn kho được chọn cho các mục được chỉ định cho CategoryId. Tuy nhiên, để điền vào bộ sưu tập Khoảng không quảng cáo của phần tử Lưu trữ, truy vấn cũng phải trả lại tất cả các hàng Khoảng không quảng cáo sử dụng cùng một StorageId (và sau đó tất cả các hàng ProductItem và Sản phẩm tương ứng cho các bản ghi Khoảng không quảng cáo bổ sung đó. 'd bắt đầu bằng cách xóa bộ sưu tập Khoảng không quảng cáo khỏi phần tử Bộ nhớ hoặc loại bỏ bao gồm tương ứng.

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