11

我在IQueryable<T>整个应用程序中使用接口,并将数据库上的 SQL 执行推迟到像这样的方法.ToList()

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

IQueryable<T>所以我的问题是:从'Count()方法返回计数比将 ' 渲染IQueryable<T>到列表并调用列表的方法在数据库上的工作会更少Count()吗?

我怀疑它会ToList()触发 SELECT sql,然后在单独的查询中计算行数。我希望Count()onIQueryable<T>只是为 sql COUNT() 查询呈现 sql。但我不确定。你知道吗?

4

3 回答 3

21

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

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

但是,检查这一点的最简单方法是在您的数据上下文中启用日志记录(或您的特定提供者的任何等效项)并查看实际发送的查询。

于 2009-02-16T10:46:34.527 回答
-1

我不确定这是否是一个硬性规定,但您添加到 Iqueryable 的 linq 方法将被添加到 linq 表达式树中 - 除非它们是实际导致树被评估的方法之一(如 ToList 和 Single ETC)。在 LinqToSql 的情况下,您会知道它是否无法将某些内容转换为 SQL 语句,因为您会收到一个运行时异常,说明该方法不受支持。

例如

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

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

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

于 2009-02-18T02:46:10.310 回答
-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();
}
于 2011-05-15T05:35:07.413 回答