【问题标题】:Optimising a linq query to be as fast as doing the same in sql优化 linq 查询与在 sql 中执行相同的操作一样快
【发布时间】:2015-09-30 21:45:46
【问题描述】:

我正在努力完善我对 Linq 的了解和使用。我有一个从标准 sql 数据库构建的实体框架模型。

在标准 sql 中,我可以执行以下查询:

    DECLARE 
 @VesselId int = 1


  SELECT COALESCE(c.CompanyName,c.FirstName + ' ' + c.LastName) FROM dbo.Contacts c
  WHERE c.ContactId = (SELECT v.OwnerId FROM dbo.Vessels v WHERE v.VesselId = @VesselId)

根据 ssms 执行需要 0.00.00.029 秒。

现在我尝试将其转换为 linq 以在我的模型中运行,并且到目前为止已经提出了这个(我一直在 Linqpad 中测试(因此是转储语句)):

Sub Main
    Dim name As String = GetOwnersName(1)
    name.Dump
End Sub


Private Function GetOwnersName(ByVal id As Integer) As String
    Dim myContact As Contact

    Dim query = From c In Contacts
                   Where c.ContactId = (From v In Vessels
                                        Where v.VesselId = id
                                        Select v.OwnerId
            ).FirstOrDefault
                   Select c

    myContact = query.FirstOrDefault

    Return  If(myContact.CompanyName, myContact.FirstName + " " + myContact.LastName)


End Function

这在 0.00.00.065 秒内执行。我知道第一个 sql 查询是直接在 sql server 上执行的,但我怀疑 linq 可以被优化以提高效率。我希望通过使用在两种环境中我都能清楚理解的东西(我承认对 sql 更满意),我可以改进我的 linq。服务器上的联系人表有大约 40 多个字段,我确信在 linq 示例中返回所有这些字段并不能提高速度。

任何人都可以建议如何改进 linq,是否可以解释为什么可以这样,以便我可以从中学习。

谢谢

编辑 linq 的最新版本。可以改进吗?

Sub Main
    Dim name As String = GetOwnersName(4)
    name.Dump
End Sub


Private Function GetOwnersName(ByVal id As Integer) As String

    Dim query = From c In Contacts
                   Where c.ContactId = (From v In Vessels
                                        Where v.VesselId = id
                                        Select v.OwnerId
            ).FirstOrDefault
                   Select (If( c.CompanyName, c.FirstName + " " + c.LastName))

    Return query.FirstOrDefault
End Function

【问题讨论】:

    标签: sql vb.net linq


    【解决方案1】:

    第一个查询本质上是

    (From c In Contacts
    Where c.ContactId = (From v In Vessels
                        Where v.VesselId = id
                        Select v.OwnerId).FirstOrDefault
    Select c)
    .FirstOrDefault
    

    这将从数据库中获取完整的Contact,因此它与您显示的 SQL 完全不同。

    第二个查询更像是因为你只从Contact中选择了需要的列。

    与性能问题一样,很难说这里是否有任何改进之处。唯一的(可能是次要的)改进可能是使用连接而不是子查询。在 SQL 中:

    SELECT COALESCE(c.CompanyName,c.FirstName + ' ' + c.LastName)
    FROM dbo.Contacts c
    INNER JOIN dbo.Vessels v ON v.OwnerId = v.VesselId
    WHERE v.VesselId = @VesselId
    

    在 VB 中:

    From c In Contacts
    c.Vessel.VesselId = id
    Select (If( c.CompanyName, c.FirstName + " " + c.LastName))
    

    (不是Join,而是一个导航属性)。

    【讨论】:

      【解决方案2】:

      将其他表中的字段添加到您尝试查询的表中。 我知道拥有冗余字段听起来很可怕,但是当不得不经常查询这些表时,它确实可以挽救生命。 通过将结果值添加到行来减少查询中需要进行的计算量。

      只要您为不断变化的值处理好触发器,那么您将拥有一个有点庞大但速度很快的数据库。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-27
        • 1970-01-01
        • 1970-01-01
        • 2019-10-20
        相关资源
        最近更新 更多