算在LINQ中选择VS - 哪个更快?

时间:2009-02-16 10:41:50

标签: sql linq performance iqueryable

我在整个应用程序中使用IQueryable<T>接口,并推迟在DB上执行SQL,直到像.ToList()

这样的方法

我有时需要查找某些列表的计数 - 而不需要使用列表中的数据进行计数。根据我的SQL经验,我知道SQL COUNT()的工作量远远少于返回所有行的等效SELECT语句。

所以我的问题是:数据库从IQueryable<T>的{​​{1}}方法返回计数,而不是将Count()渲染到列表并调用列表IQueryable<T>方法?

我怀疑它会给Count()激活SELECT sql然后在单独的查询中计算行数。我希望ToList()上的Count()只是简单地为sql COUNT()查询呈现sql。但我不确定。你知道吗?

3 个答案:

答案 0 :(得分:21)

调用ToList()将返回包含所有数据的真实List<T>,这意味着获取所有数据。不好。

调用Count()确实应该使SQL在数据库端进行计数。好多了。

然而,检查此问题的最简单方法是启用数据上下文中的日志记录(或任何与您的特定提供程序等效的内容)并查看实际发送的查询。

答案 1 :(得分:-1)

我不确定它是否是一个硬性规则,但是你添加到Iqueryable的linq方法将被添加到linq表达式树中 - 除非它们是实际导致树被评估的方法之一(如ToList和Single等)。 对于LinqToSql,您将知道它是否无法将某些内容转换为SQL语句,因为您将获得一个运行时异常,指出该方法不受支持。

例如

var something = dbContext.SomeTable
  .Select(c => c.col1 == "foo")
  .Distinct()
  .ToList()
  .Count()

在上面,Select()和Distinct()包含在传递给服务器的sql查询中,因为它们被添加到Iqueryable中。 Count()只是作用于sql查询返回的列表。所以你不想这样做: - )

在你的情况下,Count()肯定会比Select()更快,因为生成的sql语句确实会包含计数,所以服务器只需要返回一个数字而不是一个行列表。

答案 2 :(得分:-1)

如果您正在使用SQL Server,Count()仍然非常昂贵,因为它会导致表扫描(或索引扫描,请参阅主要答案的注释)。并且,默认情况下,Linq不使用读取未注册的隔离级别,这会因锁定而使事情变得更糟。

如果您可以将结果视为脏结果和行总数的近似值,则以下代码将比使用Count()快得多。根据我的经验,此代码返回的值很少与行的真实数量不同。

/// <summary>A very fast method for counting rows in a table.</summary>
public static long FastRowCount(DataContext context, string tableName)
{
    const string template = "SELECT rowcnt FROM sys.sysindexes WHERE id = OBJECT_ID('{0}') AND indid < 2";
    string query = string.Format(template, tableName);
    return context.ExecuteQuery<long>(query).Single();
}
相关问题