提高linq查询效率

提高linq查询效率,linq,linq-to-entities,Linq,Linq To Entities,我正在优化我的web应用程序,遇到了瓶颈,从linq表达式生成的SQL非常慢 以下SQL在不到一秒钟的时间内执行良好: SELECT ISNULL(COUNT(distinct JOBIDNumber),0), ISNULL(SUM(JIMQuantityActual * JIMNetMarginFactor),0), ISNULL(sum((isnull(MATRecoverablePercent,0) / 100) * JIMQuantityActual * JIMN

我正在优化我的web应用程序,遇到了瓶颈,从linq表达式生成的SQL非常慢

以下SQL在不到一秒钟的时间内执行良好:

SELECT
    ISNULL(COUNT(distinct JOBIDNumber),0),
    ISNULL(SUM(JIMQuantityActual * JIMNetMarginFactor),0),
    ISNULL(sum((isnull(MATRecoverablePercent,0) / 100) * JIMQuantityActual * JIMNetMarginFactor),0),
    ISNULL(sum(CarbonSaving),0)
FROM
    dbo.fn_GetJobsForUser(183486) jb
    inner join cd_JobMaterial on JIMJobId = jb.JOBIDNumber
WHERE
    JOBCollectionDate >= '2014-11-01'
而以下查询对相同数据的sql输出需要4到16秒:

DateTime d = new DateTime(2014, 11, 1)

from job in sp.sp_GetJobsForUser(183486)
where job.JOBCollectionDate >= d
join material in UnitOfWork.Repository<cd_JobMaterial>().Queryable()
on job.JOBIDNumber equals material.JIMJobId 
group material by 1 into f
select new
{
     Jobs = f.Distinct().Count(),
     Weight = f.Sum(x=> x.JIMQuantityActual * x.JIMNetMarginFactor),
     Carbon = f.Sum(x=> x.CarbonSaving),
     Recovery = f.Sum(x => ((x.MATRecoverablePercent / 100) * x.JIMQuantityActual * x.JIMNetMarginFactor))
}

如何重新编写linq表达式以生成更高效的sql,还是仅仅编写一个存储过程并使用它?

不幸的是,这是使用实体框架这样灵活的东西的缺点之一,它必须支持各种复杂的转换。当然,它在其他方面也有很大的好处,所以您必须在性能方面进行平衡

即使您现在可以找到一种重写查询的方法来生成更好的SQL,这也取决于未来版本中底层提供程序的更改。在应用程序不再接受性能之前,尽可能长时间地享受干净、简洁的代码。如果EF在这一点上没有进行切割,那么就使用提供的一些钩子来执行原始SQL、存储过程等,这些钩子就没有那么漂亮了

-- Region Parameters
DECLARE @contactId Int = 183486
DECLARE @p__linq__0 DateTime2 = '2014-11-01 00:00:00.0000000'
-- EndRegion

SELECT
    [Project4].[C1] AS [C1],
    [Project4].[C5] AS [C2],
    [Project4].[C2] AS [C3],
    [Project4].[C3] AS [C4],
    [Project4].[C4] AS [C5]
FROM (SELECT
    [Project2].[C1] AS [C1],
    [Project2].[C2] AS [C2],
    [Project2].[C3] AS [C3],
    [Project2].[C4] AS [C4],
    (SELECT
        COUNT(1) AS [A1]
    FROM (SELECT DISTINCT
        /*Fields omitted for brevity */
    FROM [dbo].[fn_GetJobsForUser](@contactId) AS [Extent3]
    INNER JOIN (SELECT
        /*Fields omitted for brevity */
    FROM [dbo].[cd_JobMaterial] AS [cd_JobMaterial]) AS [Extent4]
        ON [Extent3].[JOBIDNumber] = [Extent4].[JIMJobId]
    WHERE ([Extent3].[JOBCollectionDate] >= @p__linq__0)
    AND ([Project2].[C1] = 1)) AS [Distinct1])
    AS [C5]
FROM (SELECT
    @contactId AS [contactId],
    @p__linq__0 AS [p__linq__0],
    [GroupBy1].[K1] AS [C1],
    [GroupBy1].[A1] AS [C2],
    [GroupBy1].[A2] AS [C3],
    [GroupBy1].[A3] AS [C4]
FROM (SELECT
    [Project1].[K1] AS [K1],
    SUM([Project1].[A1]) AS [A1],
    SUM([Project1].[A2]) AS [A2],
    SUM([Project1].[A3]) AS [A3]
FROM (SELECT
    1 AS [K1],
    [Project1].[JIMQuantityActual] * [Project1].[JIMNetMarginFactor] AS [A1],
    [Project1].[CarbonSaving] AS [A2],
    ([Project1].[MATRecoverablePercent] / CAST(100 AS DECIMAL(18))) * [Project1].[JIMQuantityActual] * [Project1].[JIMNetMarginFactor] AS [A3]
FROM (SELECT
    [Extent2].[MATRecoverablePercent] AS [MATRecoverablePercent],
    [Extent2].[JIMQuantityActual] AS [JIMQuantityActual],
    [Extent2].[JIMNetMarginFactor] AS [JIMNetMarginFactor],
    [Extent2].[CarbonSaving] AS [CarbonSaving]
FROM [dbo].[fn_GetJobsForUser](@contactId) AS [Extent1]
INNER JOIN (SELECT
    /*Fields omitted for brevity */
FROM [dbo].[cd_JobMaterial] AS [cd_JobMaterial]) AS [Extent2]
    ON [Extent1].[JOBIDNumber] = [Extent2].[JIMJobId]
WHERE [Extent1].[JOBCollectionDate] >= @p__linq__0) AS [Project1]) AS [Project1]
GROUP BY [K1]) AS [GroupBy1]) AS [Project2]) AS [Project4]