c# - Linq 性能 : should I first use `where` or `select`

标签 c# performance linq linq-to-entities query-performance

我在内存中有一个很大的 List,来自一个具有大约 20 个 properties 的类。

我想仅根据一个property 过滤此列表,对于特定任务我只需要该property 的列表。所以我的查询是这样的:

data.Select(x => x.field).Where(x => x == "desired value").ToList()

先使用 Select 还是使用 Where 哪个性能更好?

data.Where(x => x.field == "desired value").Select(x => x.field).ToList()

如果这与我将数据保存在内存中的数据类型 或字段类型有关,请告诉我。请注意,我也需要这些对象来执行其他任务,因此我无法在将它们加载到内存之前首先过滤它们。

最佳答案

Which one gives me a better performance, using Select first, or using Where.

Where 第一种方法性能更高,因为它首先过滤您的集合,然后仅对过滤 值执行Select

从数学上讲,Where-first 方法采用N + N' 操作,其中N' 是属于集合项的数量你的 Where 条件。
因此,它至少需要 N + 0 = N 操作(如果没有项目通过此 Where 条件)和 N + N = 2 * N最多操作(如果所有项目都通过条件)。

与此同时,Select 第一种方法将始终恰好进行 2 * N 操作,因为它遍历所有对象以获取属性,然后遍历所有对象对象来过滤它们。

基准证明

我已经完成了基准测试来证明我的答案。

结果:

Condition value: 50
Where -> Select: 88 ms, 10500319 hits
Select -> Where: 137 ms, 20000000 hits

Condition value: 500
Where -> Select: 187 ms, 14999212 hits
Select -> Where: 238 ms, 20000000 hits

Condition value: 950
Where -> Select: 186 ms, 19500126 hits
Select -> Where: 402 ms, 20000000 hits

如果您多次运行基准测试,那么您会发现 Where -> Select 方法的命中率不时发生变化,而 Select -> Where 方法总是采用2N 操作。

IDEOne演示:

https://ideone.com/jwZJLt

代码:

class Point
{
    public int X { get; set; }
    public int Y { get; set; }
}

class Program
{
    static void Main()
    {
        var random = new Random();
        List<Point> points = Enumerable.Range(0, 10000000).Select(x => new Point { X = random.Next(1000), Y = random.Next(1000) }).ToList();

        int conditionValue = 250;
        Console.WriteLine($"Condition value: {conditionValue}");

        Stopwatch sw = new Stopwatch();
        sw.Start();

        int hitCount1 = 0;
        var points1 = points.Where(x =>
        {
            hitCount1++;
            return x.X < conditionValue;
        }).Select(x =>
        {
            hitCount1++;
            return x.Y;
        }).ToArray();

        sw.Stop();
        Console.WriteLine($"Where -> Select: {sw.ElapsedMilliseconds} ms, {hitCount1} hits");

        sw.Restart();

        int hitCount2 = 0;
        var points2 = points.Select(x =>
        {
            hitCount2++;
            return x.Y;
        }).Where(x =>
        {
            hitCount2++;
            return x < conditionValue;
        }).ToArray();

        sw.Stop();
        Console.WriteLine($"Select -> Where: {sw.ElapsedMilliseconds} ms, {hitCount2} hits");

        Console.ReadLine();
    }
}

相关问题

您也可能对这些问题感兴趣。它们与 SelectWhere 无关,但它们与 LINQ 订单性能有关:

Does the order of LINQ functions matter?
Order of LINQ extension methods does not affect performance?

关于c# - Linq 性能 : should I first use `where` or `select` ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39198086/

相关文章:

c# - IIS 中托管的 tcp 端点的 WCF 路由

mysql - 使用正确数据类型的性能优势

C# 试图避免重复

c# - FindAll 与 Where

c# - 是否可以在 C# 的 if-else 语句中定义类似 'between' 的内容?

c# - Azure Blob 存储 - MVC Web 应用程序 - 有没有办法直接上传到 Azure Blob 存储而不通过 MVC Web 应用程序?

mysql - 这两个字段中哪一个会导致更快的数据库查询?

c# - LINQ 查询根据匹配的另一个表从一个表返回

c# - User.Identity.GetUserId 是缓存还是每次都从数据库中获取?

performance - 加速 Levy 运动算法的仿真