2015-04-16 142 views
9

嗨,大家好,我正面臨性能問題。
當我運行此查詢與日期時間內查詢linq查詢優化日期時間

var temp = (from p in db.BEM_EVT_FULL 
         where (p.date_reception > new DateTime(2015,01,01)) 
         group p by p.mc_object into g 
         orderby g.Count() descending 
         select new StringIntType 
         { 
          str = g.Key, 
          nbr = g.Count()}).Take(50).ToList(); 

SQL Server Profiler中宣佈它翻譯成該查詢

SELECT TOP (50) 
[Project1].[C3] AS [C1], 
[Project1].[mc_object] AS [mc_object], 
[Project1].[C2] AS [C2] 
FROM (SELECT 
    [GroupBy1].[A1] AS [C1], 
    [GroupBy1].[A2] AS [C2], 
    [GroupBy1].[K1] AS [mc_object], 
    1 AS [C3] 
    FROM (SELECT 
     [Extent1].[mc_object] AS [K1], 
     COUNT(1) AS [A1], 
     COUNT(1) AS [A2] 
     FROM [dbo].[BEM_EVT_FULL] AS [Extent1] 
     WHERE [Extent1].[date_reception] > convert(datetime2, '2015-01-01 00:00:00.0000000', 121) 
     GROUP BY [Extent1].[mc_object] 
    ) AS [GroupBy1] 
) AS [Project1] 
ORDER BY [Project1].[C1] DESC 

,它工作得很好那你現在就當1S

下執行我宣佈DateTime外部查詢和我運行此查詢

DateTime dt = new DateTime(2015,01,01); 

     var temp = (from p in db.BEM_EVT_FULL 
         where (p.date_reception > dt) 
         group p by p.mc_object into g 
         orderby g.Count() descending 
         select new StringIntType 
         { 
          str = g.Key, 
          nbr = g.Count() 
         }).Take(50).ToList(); 

SQL Server Profiler中它翻譯成該查詢

exec sp_executesql N'SELECT TOP (50) 
[Project1].[C3] AS [C1], 
[Project1].[mc_object] AS [mc_object], 
[Project1].[C2] AS [C2] 
FROM (SELECT 
    [GroupBy1].[A1] AS [C1], 
    [GroupBy1].[A2] AS [C2], 
    [GroupBy1].[K1] AS [mc_object], 
    1 AS [C3] 
    FROM (SELECT 
     [Extent1].[mc_object] AS [K1], 
     COUNT(1) AS [A1], 
     COUNT(1) AS [A2] 
     FROM [dbo].[BEM_EVT_FULL] AS [Extent1] 
     WHERE [Extent1].[date_reception] > @p__linq__0 
     GROUP BY [Extent1].[mc_object] 
    ) AS [GroupBy1] 
) AS [Project1] 
ORDER BY [Project1].[C1] DESC',N'@p__linq__0 datetime2(7)',@p__linq__0='2015-01-01 00:00:00' 


這需要大約5MN得到exectued,所有的差異,因爲日期時間報關的,我需要知道我應該作出什麼樣的變化申報日期時間outisde查詢,獲得與第一個查詢相同的性能。

+0

任何線索從http://stackoverflow.com/questions/3710523/sql-server-sp-executesql-and-execution-plans? – tschmit007

+0

數據庫中是否有'[date_reception]'的索引?那麼'[mc_object]'呢? –

+0

是的,我有兩個索引 –

回答

0

對此(我相信)的原因是,在第一種情況下,DateTime是一個編譯時間常量,但在第二種情況下,它不是,因此EF必須將它作爲參數傳遞。

+0

我不明白爲什麼這會造成如此大的差異查詢雖然... –

+0

我想象因爲第一個查詢計劃被緩存,而第二個不能被緩存。 –

+0

我不認爲'DateTime's可以是編譯時間常量。 –

0

我的猜測是,對於常量值,SQL編譯器知道如何創建最高效的計劃,但是使用參數,它不會,所以它必須猜測,任何人都可能猜得很糟糕。由於第一個查詢只返回50條記錄,仍然需要幾分鐘的時間運行我認爲[date_reception][mc_object]應該幫助添加索引(或重新索引如果索引已經存在)。如果這些不起作用,您可能會被迫手動構建SQL,而不是使用Linq,因爲您無法控制Linq生成的SQL。

+0

不幸的是,索引已經存在了,我想我會和你的最後一個解決方案一起進行。 –

+0

在開球之前,你可能還會看看執行計劃(也許可以在http://dba.stackexchange.com上重新發布)。還重新索引您的表格,看看是否沒有幫助。 –

1

我想你的表中有很多行,並且值2015-01-01 00:00:00提供了足夠的過濾來消除許多行(比如8個),並且值得使用相應的索引。

使用變量,與簡單表掃描相比,查詢優化器不知道變量是否會提供足夠的過濾。 它威力判斷它是不值得使用索引(尤其是如果指數有一個包括用於查詢。According to your previous question沒有相關條款,也可能是這種情況)

它也可能產生壞的查詢計劃,因爲「參數嗅探」

無論如何,您可能會嘗試使用專用查詢攔截器引入強制「選項重建」。請參閱 https://stackoverflow.com/a/26762756/1236044

0

試圖找出執行計劃中的差異。在this experiment這是不同的,因爲該列被聲明爲日期時間,並且比較符被聲明爲不同。在一種情況下,它是一個內聯語句,另一種情況下是一個聲明的變量。如果您將該字段聲明爲datetime2,則執行計劃中沒有區別。