Linq SQL计数方法性能问题

时间:2019-01-07 12:34:35

标签: c# sql-server performance linq entity-framework-6

我有一个代码优先的数据库,其中包含两个表:campaign和campaignItem。

广告系列可以包含许多广告系列项目。

在一种方法中,我想从某个广告系列中获取所有失败的广告系列项目的数量。现在我的问题开始了:

首先使用此代码:

long id = 593;
var failedCount = db.CampaignItems.Count(x => x.CampaignId == id && x.Status == CampaignItemStatus.Failed);

生成的SQL命令为:

exec sp_executesql N'SELECT 
    [GroupBy1].[A1] AS [C1]
    FROM ( SELECT 
        COUNT(1) AS [A1]
        FROM [dbo].[CampaignItems] AS [Extent1]
        WHERE ([Extent1].[CampaignId] = @p__linq__0) AND (0 = [Extent1].[Status])
    )  AS [GroupBy1]',N'@p__linq__0 bigint',@p__linq__0=593

这太慢了。差不多2秒但是当我直接执行它时,速度非常快。 之后,我尝试执行其他操作以检查此查询为何如此缓慢。

我第一次尝试使用直接查询

db.Database.SqlQuery<int>("SELECT [GroupBy1].[A1] AS [C1] FROM ( SELECT  COUNT(1) AS [A1]         FROM [dbo].[CampaignItems] AS [Extent1]         WHERE (593 = [Extent1].[CampaignId]) AND (0 = [Extent1].[Status])     )  AS [GroupBy1] ").First();

db.Database.SqlQuery<int>("exec sp_executesql N'SELECT      [GroupBy1].[A1] AS [C1]    FROM ( SELECT         COUNT(1) AS [A1]        FROM [dbo].[CampaignItems] AS [Extent1]        WHERE ([Extent1].[CampaignId] = @p__linq__0) AND (0 = [Extent1].[Status])    )  AS [GroupBy1]',N'@p__linq__0 bigint',@p__linq__0=593").First();

获得快速结果(少于150毫秒)

之后,我尝试其他一些LINQ示例。

我发现是否使用常量值而不是变量,生成的查询是不同的,并且非常快。因此,以下代码会很快产生结果:

var failed = db.CampaignItems.Count(x => x.CampaignId == 593 && x.Status == CampaignItemStatus.Failed);

之后,我尝试添加另一个变量。我猜应该会很慢,因为现在有两个变量。我使用thsis代码:

long id = 593;
var validState = CampaignItemStatus.Failed;
var failedCount = db.CampaignItems.Count(x => x.CampaignId == id && x.Status == validState);

SQL生成的查询为:

exec sp_executesql N'SELECT 
    [GroupBy1].[A1] AS [C1]
    FROM ( SELECT 
        COUNT(1) AS [A1]
        FROM [dbo].[CampaignItems] AS [Extent1]
        WHERE ([Extent1].[CampaignId] = @p__linq__0) AND ([Extent1].[Status] = @p__linq__1)
    )  AS [GroupBy1]',N'@p__linq__0 bigint,@p__linq__1 int',@p__linq__0=593,@p__linq__1=0

当结果过快时,我会感到惊讶。太神奇了。差不多150毫秒就能得到结果。

之后,我会尝试其他方法。

这次,我在LINQ查询中添加一个数字(0),如下所示:

long id = 593;
var validState = CampaignItemStatus.Failed;
failed = db.CampaignItems.Count(x => x.CampaignId == id + 0 && x.Status == validState);

生成的查询为:

exec sp_executesql N'SELECT 
    [GroupBy1].[A1] AS [C1]
    FROM ( SELECT 
        COUNT(1) AS [A1]
        FROM [dbo].[CampaignItems] AS [Extent1]
        WHERE ([Extent1].[CampaignId] = (@p__linq__0 + cast(0 as bigint))) AND ([Extent1].[Status] = @p__linq__1)
    )  AS [GroupBy1]',N'@p__linq__0 bigint,@p__linq__1 int',@p__linq__0=593,@p__linq__1=0

我再次感到惊讶。因为太快了。

现在这是我的问题:

1-为什么使用多于一个变量的速度更快?

2-为什么加上零会使速度更快?这些尝试都使查询更加复杂

3-我该如何做才能使我的普通代码快速运行而又没有诸如添加废话变量或添加零之类的怪异东西?

ps:广告系列项目表几乎有1,000,000行        女巫中有近40万行是失败的物品

ps 2:@mjwills:是的。每次我运行查询30次并获得平均时间。清除缓存没有意义。  @托马斯·韦勒:你很严厉。我也测试这种情况。那也很快。但是问题很长,我没有将所有结果都放在这里。

0 个答案:

没有答案