你会允许这种类型的查询吗?

时间:2011-01-10 00:32:27

标签: tsql entity-framework sql-server-2008

我正在探索在我们的开发商店中使用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

2 个答案:

答案 0 :(得分: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 :(得分:1)

似乎有一个不必要的派生表,它几乎使查询的长度加倍。它不太可能对运行时性能产生显着影响,因此不值得担心。

从性能角度来看,更令人不安的是在WHERE子句中使用将阻止使用索引的函数。

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

它应该是一个适当的不区分大小写的排序规则:

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

但实际上这可能不是问题。