LINQ的可扩展性如何?

时间:2008-10-18 00:11:21

标签: .net linq scalability

最近与同事的谈话对此事产生了不同的观点。什么说你,SO成员?

我知道,甚至可扩展性的概念也可以采用许多不同的方式和背景,但这是讨论的一部分。每个人似乎都对可伸缩性的真正含义有不同的看法。我很想知道这里的变化也是如此。事实上,我只为这个概念发布了question

10 个答案:

答案 0 :(得分:10)

我猜想检查的最佳方法是编写基准测试,但在我看来,LINQ有可能优化手工编写类似的代码。我不知道它如何利用这些。

LINQ可让您表达您想要的内容,而不是如何生成它。一个明显的优点是LINQ可以自动并行化(参见PLINQ)。

LINQ的另一个优点是它很懒,所以你可以根据需要从集合中进行计算。您可以手动编写等效的代码,但在LINQ中可能更容易实现。

答案 1 :(得分:10)

在测试中,LINQ to objects(ForEach)比foreach循环慢约2倍。

LINQ to SQL(MS SQL数据库)几乎 10x 比使用数据读取器的直接查询慢,使用大部分时间从表达式树创建SQL(所以,你将是CPU绑定和数据库将空转) 为避免这种情况,您必须使用已编译的查询。

See this了解更多信息。帖子中的大多数信息仍然适用于.NET 3.5 SP1。

答案 2 :(得分:9)

这个问题有点像问“收藏的可扩展性如何?”

我们来谈谈对象的LINQ。一般来说,在IEnumerable<T>的大多数实现迭代基础集合中的每个项目的程度上,LINQ具有很大的扩展能力。创建一个包含一千万个项目的List<Foo>,如下所示:

var list = from Foo f in fooList
           where f.Value = "Bar"
           select f;

会变慢。但这确实不是LINQ的错。你是那个给它一千万件物品清单的人。

如果LINQ不存在,你就像处理它一样处理它:通过构建Dictionaries和SortedLists等来帮助你减少搜索空间。

LINQ可以通过延迟查询执行来提高可伸缩性(以及更容易实现可伸缩性)。您可以使用一系列LINQ查询替换创建列表,将其过滤到新列表,过滤到新列表等的天真方法:

var list1 = from Foo f in fooList where f.Value1 = "Bar" select f;
var list2 = from Foo f in list1 where f.Value2 = "Baz" select f;
var list3 = from Foo f in list2 where f.Value3 = "Bat" select f;

所有这些都是通过底层集合执行的,当(以及是否)需要迭代最终列表时。但是,这并不是什么新鲜事:如果你没有LINQ,你可能最终会用一个做同样事情的方法替换你的天真方法。但是LINQ使它变得容易多了。

答案 3 :(得分:7)

在我看来,LINQ旨在从开发的角度简化事情,而不是解决可伸缩性问题。

实际上,使用LINQ可以通过隐藏大量复杂功能使事情变得如此简单,当不负责任地使用 时,可以引导可扩展性问题。

其他答案中有很多例子,但最重要的是:

  • 如果您要查询对象集合,则无法忽略其大小。也许在模型中使用LINQ,当有一些对象要查询时听起来不错......但随着大小的增加,很明显查询应该在数据库中发生,而不是在模型中。

    < / LI>
  • 如果您使用LINQ自动生成SQL,据我所知,您无法提供有关如何编译查询的数据库提示,例如WITH (NOLOCK)。随着您的桌面规模的增长,能够解决这些问题势在必行。

  • 与上述类似,但可能更为通用:当您通过数据库解决可伸缩性问题时,必须控制数据库正在执行的操作。使用一种编译为SQL的语言,然后再将其编译为执行计划,可以从您手中删除控制权。

  • 如果您必须更改数据库架构以使其更具可伸缩性并且您的代码与之紧密相关,因为您没有存储过程,会发生什么?

  • 虽然看起来很简单,但是你不能轻易改变LINQ提供程序:查询SQL Server与查询对象或查询XML不同。 LINQ非常相似。我确实希望我的一些初级开发人员能够进行“LINQ狂欢”,因为这比考虑如何在可扩展性方面做事更容易。

总之,我认为可以使用LINQ编写可伸缩代码,但只能小心使用它。没有杀手工具,只有杀手代码

答案 4 :(得分:3)

这在很大程度上取决于您使用的LINQ提供商以及您如何使用它。 LINQ可能并不知道具有惊人的执行速度,而是为开发人员提供了更高的生产力。

根据this链接,即使使用某些CTP,Linq to SQL在某些情况下已经比使用直接SQL更好了。

如果您关心Speed并且正在使用LINQ to objects here是一个代码复合项目(我认为),它可以为您提供1000倍的性能提升。

答案 5 :(得分:3)

关于可扩展性的问题在某些方面取决于您使用LINQ的内容。在业务应用程序中,您不会发现很多SQL命令正在执行 - 它们很慢并且必须在DBMS中编译。你会看到的是很多存储过程调用。 LINQ中的这些会稍快一点。

请记住,LINQ to SQL等建立在ADO.NET的TOP之上 - 它们不是完全不同的方法或任何东西。当然,LINQ to XML将使用不同的API。这将非常类似于编译器 - 人类总能做出一些可能更快的优化,但在大多数情况下,这些API将能够生成比您自己编写的代码更快,更少错误的代码。

就扩展而言,如果要稍微分发数据或者可以使用SQL Server复制,则可以始终将LINQ置于Web服务之后。它的可扩展性不应低于ADO.NET。

答案 6 :(得分:1)

可伸缩性和性能是两个不同但相关的东西。如果要测量性能,则需要查看一个框可以支持多少用户(例如)。当您测量可扩展性时,您可以添加另一个框,看看是否可以支持原始数量的两倍?不太可能,你可能只增加75%的处理能力,下一个只增加原始单位的50%,因此它会很快降到零。无论您以该速率添加多少个盒子,您都很幸运能够将支持的用户数增加一倍。这是可扩展性。

Linq模块如何扩展可能更多地取决于数据库,机器的强大程度,数据库的设计是什么,应用程序的设计是什么。

你经常会看到微观基准,它们应该揭示某些结论性的东西,但它们永远不会这样做,因为它们只是对整个问题的关键洞察。

你可以在这里拉出好的旧20/80例子。这个工具可能占20%,构成应用程序的各种有形物占80%。

答案 7 :(得分:1)

如果你正在寻找一个真实的例子,stackoverflow大量使用Linq,请检查post/podcast

答案 8 :(得分:1)

使用Linq to SQL框架按需缓存和加载对象是有代价的。 如果一个对象可以根据需要延迟加载自身的一部分,那么很可能在每个对象中都有对数据上下文的引用。顺便提一下,数据上下文还会缓存从中请求的每个对象。这意味着如果您保留一个对象(在缓存中或仅仅因为稍后使用它),您不仅要保留该对象,而且还要保留数据上下文所请求的每个对象。这些将永远不会被垃圾收集,因为它们仍然被引用。

如果您的所有目标都具有较短的生命周期,并且应用程序每次执行新工作时都会创建新的DataContexts,则这不是问题。但我可以看到它是如何产生可扩展性问题的,如果有人不知道与每个对象一起出现的额外阻碍。

答案 9 :(得分:0)

Linq在许多方面都是scalabile。

一个方面是linq背后的规范实现,它允许将Expression解释为以不同的语言(Linq2Sql,Linq2Hibernate)或在分布式计算环境(例如map-reduce集群)中耗尽进程( DryadLINQ

另一个方面是linq为语言提供的语义。如果您的提供程序支持延迟加载,您可以迭代数十亿个对象而无需在内存中填充集合,或者您可以对该查询进行并行化或优化(PLINQ或i4o)。