2011-01-10 25 views
1

我正在探索在我們的開發工作室中使用ORM工具,特別是Entity Framework 4.0。由於我們使用非常大的數據庫,因此我對它產生的查詢有點擔心。你會允許這種類型的查詢嗎?

做一些簡單的事情,比如在一個狀態下獲取客戶端地址如下所示。

作爲數據庫開發人員或管理員,你會允許這麼做嗎?它看起來很糟嗎?假設每個連接都在聚簇索引上。

SELECT 
[Project2].[ClientKey] AS [ClientKey], 
[Project2].[FirstName] AS [FirstName], 
[Project2].[LastName] AS [LastName], 
[Project2].[IsEnabled] AS [IsEnabled], 
[Project2].[ChangeUser] AS [ChangeUser], 
[Project2].[ChangeDate] AS [ChangeDate], 
[Project2].[C1] AS [C1], 
[Project2].[AddressKey] AS [AddressKey], 
[Project2].[ClientKey1] AS [ClientKey1], 
[Project2].[AddressTypeCode] AS [AddressTypeCode], 
[Project2].[PrimaryAddress] AS [PrimaryAddress], 
[Project2].[AddressLine1] AS [AddressLine1], 
[Project2].[AddressLine2] AS [AddressLine2], 
[Project2].[City] AS [City], 
[Project2].[State] AS [State], 
[Project2].[ZIP] AS [ZIP] 
FROM (SELECT 
    [Distinct1].[ClientKey] AS [ClientKey], 
    [Distinct1].[FirstName] AS [FirstName], 
    [Distinct1].[LastName] AS [LastName], 
    [Distinct1].[IsEnabled] AS [IsEnabled], 
    [Distinct1].[ChangeUser] AS [ChangeUser], 
    [Distinct1].[ChangeDate] AS [ChangeDate], 
    [Extent3].[AddressKey] AS [AddressKey], 
    [Extent3].[ClientKey] AS [ClientKey1], 
    [Extent3].[AddressTypeCode] AS [AddressTypeCode], 
    [Extent3].[PrimaryAddress] AS [PrimaryAddress], 
    [Extent3].[AddressLine1] AS [AddressLine1], 
    [Extent3].[AddressLine2] AS [AddressLine2], 
    [Extent3].[City] AS [City], 
    [Extent3].[State] AS [State], 
    [Extent3].[ZIP] AS [ZIP], 
    CASE WHEN ([Extent3].[AddressKey] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1] 
    FROM (SELECT DISTINCT 
     [Extent1].[ClientKey] AS [ClientKey], 
     [Extent1].[FirstName] AS [FirstName], 
     [Extent1].[LastName] AS [LastName], 
     [Extent1].[IsEnabled] AS [IsEnabled], 
     [Extent1].[ChangeUser] AS [ChangeUser], 
     [Extent1].[ChangeDate] AS [ChangeDate] 
     FROM [Common].[Clients] AS [Extent1] 
     INNER JOIN [Common].[ClientAddresses] AS [Extent2] ON [Extent1].[ClientKey] = [Extent2].[ClientKey] 
     WHERE ((CAST(CHARINDEX(UPPER('D'), UPPER([Extent1].[LastName])) AS int)) > 0) AND ([Extent1].[IsEnabled] = 1) AND ([Extent2].[City] IS NOT NULL) AND ((UPPER([Extent2].[City])) = (UPPER('Colorado Springs')))) AS [Distinct1] 
    LEFT OUTER JOIN [Common].[ClientAddresses] AS [Extent3] ON [Distinct1].[ClientKey] = [Extent3].[ClientKey] 
) AS [Project2] 
ORDER BY [Project2].[ClientKey] ASC, [Project2].[FirstName] ASC, [Project2].[LastName] ASC, [Project2].[IsEnabled] ASC, [Project2].[ChangeUser] ASC, [Project2].[ChangeDate] ASC, [Project2].[C1] ASC 
+1

它是ORM生成這些查詢,還是查詢某些C#語句的寫入方式的結果? UPPER()的存在使我相信後者...... – 2011-01-10 01:24:28

+2

這是由什麼產生的LINQ查詢? – 2011-01-10 02:53:17

回答

2

內連接地址的客戶端...

INNER JOIN [Common].[ClientAddresses] AS [Extent2] 
    ON [Extent1].[ClientKey] = [Extent2].[ClientKey] 

與城市條件...

AND ((UPPER([Extent2].[City])) = (UPPER('Colorado Springs'))) 

現在左側再次加入地址?

LEFT OUTER JOIN [Common].[ClientAddresses] AS [Extent3] 
    ON [Distinct1].[ClientKey] = [Extent3].[ClientKey] 

左連接是多餘的,因爲行必須已經存在以符合條件。

而且它是在內部查詢這可能是不必要的,如果表是標準化

我不相信的ORM生成優化的查詢選擇不同的行。

1

似乎有一個不必要的派生表,它幾乎使查詢長度加倍。它不太可能對運行時間性能產生顯着影響,所以不值得擔心。

從性能角度來看,更麻煩的是在WHERE子句中使用函數來防止使用索引。

WHERE ... 
AND ((UPPER([Extent2].[City])) = (UPPER('Colorado Springs'))) 

這應該只是這個用適當的區分大小寫排序:

WHERE ... 
AND [Extent2].[City] = 'Colorado Springs' 

但它可能不會在實踐中的一個問題。