簡體   English   中英

實體框架Take語句,導致EF生成無效的SQL查詢

[英]Entity Framework Take statement, cause EF generates unefficient SQL query

我在EF CodeFirst中使用TakeSkip語句,用於實現Paging(正如Zoran Maksimovic本文中所述),這些語句導致EF生成這樣的SQL查詢(我的頁面大小為100):

 SELECT TOP (100) [Filter1].[Id]                AS [Id],
                  [Filter1].[SendDuration]      AS [SendDuration]
        FROM   (SELECT [Extent1].[Id] AS [Id],               
                       [Extent1].[SendDuration] AS [SendDuration],
                       row_number() OVER (ORDER BY [Extent1].[SendDuration] DESC) AS [row_number]
                       FROM   [dbo].[MyView] AS [Extent1]
                       WHERE  (1293>= [Extent1].[Id])
                )AS [Filter1]
                WHERE  [Filter1].[row_number] > 500
                ORDER  BY [Filter1].[SendDuration] DESC

但是這個sql在sql server中運行時速度很慢,但正如Boanerge在他的評論中所說的那樣使用row_number < X而不是Top(y)會導致性能提升。 我的意思是,如果我將生成的sql更改為:

     SELECT  [Filter1].[Id]                AS [Id],
                  [Filter1].[SendDuration]      AS [SendDuration]
        FROM   (SELECT [Extent1].[Id] AS [Id],               
                       [Extent1].[SendDuration] AS [SendDuration],
                       row_number() OVER (ORDER BY [Extent1].[SendDuration] DESC) AS [row_number]
                       FROM   [dbo].[MyView] AS [Extent1]
                       WHERE  (1293>= [Extent1].[Id])
                )AS [Filter1]
                WHERE  [Filter1].[row_number] > 500 and [Filter1].[row_number] <= 600
                ORDER  BY [Filter1].[SendDuration] DESC

查詢執行時間將更好,更可接受(在某些情況下,更快4或5倍)。 有沒有辦法強制EF生成第二個Sql而不是第一個Sql?

沒有看到你的完整架構等,很難確定,但對我來說,這表明缺少索引1

運行包含實際執行計划的查詢,並查看SSMS告訴您的內容 - 它通常會建議一個額外的索引。

我有一個數百萬個記錄的數據集 - 並且花了大約3天使用LINQpad,SSMS和執行計划的詳細分析來優化每個查詢。 最后,我設法通過添加3個額外的索引來節省大約96%的執行時間。


1這是一個線索,當您可以限制范圍並提高性能時,索引是必需的/將有所幫助 - 因為這表明正在執行掃描而我們不喜歡掃描...

這是算法查詢生成的雙重優勢:查詢僅與算法一樣好。 改變的唯一方法是算法決定做一些不同的事情 - 可能使用不同版本的ORM工具。 當然,“不同”並不總是和“更好”相同:)

對於非平凡的查詢,經驗豐富的SQL開發人員 - 如果配備了正確的工具(SSMS提供了您需要的大部分內容) - 通常能夠勝過許多生成的查詢。 當然,經驗不足的SQL開發人員最終可能會遇到錯誤的查詢。

大多數ORM提供了將原始SQL查詢傳遞到引擎的選項 - 但這確實會失去可移植性。 如果這是一個問題,另一個選項就是存儲過程,其中API甚至可以在不同數據庫的不同實現上相似。

您需要在這里提出的問題是:

  • 我真的針對多個數據庫提供商嗎?
  • 我很高興能夠持續維護此查詢嗎?

如果答案為“否”和“是”,您應該可以將原始SQL(可能是T-SQL)查詢傳遞給EF。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM