使用Linq Take()生成的“SELECT TOP”进行慢速SQL查询

时间:2015-12-11 11:17:58

标签: c# sql-server linq

我遇到一个简单的linq查询的性能问题:

var query = ctx.Set<AdministrativeProfile>().OrderBy(x => x.User.Lastname).Skip(9000).Take(1);

生成的SQL如下:

SELECT TOP (1) 
    [Join1].[ProfileID] AS [ProfileID], 
    [Join1].[Address] AS [Address], 
    [Join1].[BankAccountNumber] AS [BankAccountNumber], 
    [Join1].[BankAccountType] AS [BankAccountType], 
    [Join1].[BankBIC] AS [BankBIC], 
    [Join1].[BankIBAN] AS [BankIBAN], 
    [Join1].[BankName] AS [BankName], 
    [Join1].[City] AS [City], 
    [Join1].[CountryISO] AS [CountryISO], 
    [Join1].[IdentifiedUserID1] AS [IdentifiedUserID], 
    [Join1].[Phone] AS [Phone], 
    [Join1].[SocialSecurityID] AS [SocialSecurityID], 
    [Join1].[WithHoldingTaxRate] AS [WithHoldingTaxRate], 
    [Join1].[Zip] AS [Zip]
    FROM ( SELECT [Extent1].[ProfileID] AS [ProfileID], [Extent1].[Address] AS [Address], [Extent1].[BankAccountNumber] AS [BankAccountNumber], [Extent1].[BankAccountType] AS [BankAccountType], [Extent1].[BankBIC] AS [BankBIC], [Extent1].[BankIBAN] AS [BankIBAN], [Extent1].[BankName] AS [BankName], [Extent1].[City] AS [City], [Extent1].[CountryISO] AS [CountryISO], [Extent1].[IdentifiedUserID] AS [IdentifiedUserID1], [Extent1].[Phone] AS [Phone], [Extent1].[SocialSecurityID] AS [SocialSecurityID], [Extent1].[WithHoldingTaxRate] AS [WithHoldingTaxRate], [Extent1].[Zip] AS [Zip], [Extent2].[Lastname] AS [Lastname], row_number() OVER (ORDER BY [Extent2].[Lastname] ASC) AS [row_number]
        FROM  [dbo].[AdministrativeProfile] AS [Extent1]
        INNER JOIN [dbo].[vUsers] AS [Extent2] ON [Extent1].[IdentifiedUserID] = [Extent2].[IdentifiedUserId]
    )  AS [Join1]
    WHERE [Join1].[row_number] > 9000
    ORDER BY [Join1].[Lastname] ASC

此查询的运行时间约为15秒。 我读了一些关于SELECT TOP由于某种类型而变慢的事情,但我无法找到解决问题的方法。

这是执行计划 Execution plan 几点注意事项:

1).Skip(n).Take(x)一般由分页系统添加,因此我可以在不破坏通用分页的情况下修改的唯一部分是:

ctx.Set<AdministrativeProfile>().OrderBy(x => x.User.Lastname)

2)我找到了几种方法来修复SQL语句并使其快速闪电(如在子查询中使用INNER HASH JOIN,或添加一个额外的where子句来检查[Join1].[row_number] < x),但是它是由linq查询生成的,它对我没什么帮助

3)当Skip(x)使用x的小数字时,它会更快地运行。执行时间随着x的大小而增加。

4)我使用的表没有很多行。每个约9000。

基本上,我知道如何修复SQL,但我不知道如何更改linq查询以优化它。

1 个答案:

答案 0 :(得分:0)

您应该剖析查询并查看瓶颈所在。但是,我已经处理了类似的问题,并且应该通过向您排序的属性non-clustered index添加Addy Osmani's Book:来缓解这种问题。{/ p>

基本上说:你必须跳过的成员越多,必须执行的排序就越多:使用索引时排序会变得更快。