将 .ToArray() 放入 from/in [重复] 时,LINQ 查询性能不佳

Posted

技术标签:

【中文标题】将 .ToArray() 放入 from/in [重复] 时,LINQ 查询性能不佳【英文标题】:LINQ query has bad performance while putting .ToArray() inside from/in [duplicate] 【发布时间】:2021-01-11 16:21:27 【问题描述】:
// the following approach takes sooooooo long
var result = (
    from t in (
        from a in ctx.t1
        from b in ctx.t2
        where a.id == b.id
        select new  a, b 
    ).ToArray()
    from c in ctx.t3.ToArray()
    where c.name.Contains(t.a.name)
    select new  t.a, t.b, c 
).ToArray();

// while the following approach takes time in seconds
var tSet = (
    from a in ctx.t1
    from b in ctx.t2
    where a.id == b.id
    select new  a, b 
).ToArray();
var cSet = ctx.t3.ToArray();
var result = (
    from t in tSet
    from c in cSet 
    where c.name.Contains(t.a.name)
    select new  t.a, t.b, c 
).ToArray();

请考虑上面的代码。 FMPOV,这两种方法与数据集 (t1 & t2) 和 t3 相同,这两种方法都将在 caluse 应用于它们的“第二”之前进行评估。

但是,实际情况是第一种方法比第二种方法花费的时间要长得多。我可以知道为什么吗?

提前致谢。

【问题讨论】:

那是因为第一个被翻译成类似tSet.SelectMany(t => ctx.t3.ToArray().Select(...)) 的东西所以它在t3 表上为您从第一个查询获得的t1 表中的每一行执行ToArray意味着不仅仅是两个 SQL 查询。对ToArrayToList 进行中间调用通常是个坏主意。 为什么将ToArray 放在 LINQ 查询中? @juharr 谢谢。这应该是正确的答案。 【参考方案1】:

当您枚举数据(调用 ToArray、ToList 等)时,必须首先从数据库中获取该数据。将这些以及其他未在数据库中实现的枚举方法(作为本机操作或存储过程)视为数据库事务的结束。

您应该推迟枚举数据,直到绝对必要为止。

【讨论】:

以上是关于将 .ToArray() 放入 from/in [重复] 时,LINQ 查询性能不佳的主要内容,如果未能解决你的问题,请参考以下文章

将 hashmap 转换为 stringarray

toArray方法-转载

List的toArray()方法和toArray(T[] a)方法

IN_MOVE_TO 是不是直接跟随 inotify 中的 IN_MOVE_FROM?

如何将 toArray 结果转换为 CompletableFuture<Texture>[] 类型? [复制]

toArray()方法使用说明