16

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

我知道,即使是可扩展性的概念也可以用许多不同的方式和背景来理解,但这是讨论的一部分。对于可扩展性的真正含义,每个人似乎都有不同的看法。我也很想看到这里的变化。事实上,我只是针对这个概念发布了一个问题。

4

10 回答 10

10

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

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

LINQ 的另一个优点是它是惰性的,因此您可以执行计算,根据需要从集合中绘图。您可以手动编写等效的代码,但在 LINQ 中正确使用可能要容易得多。

于 2008-10-18T00:20:39.793 回答
10

在我们所做的测试中,LINQ to objects (ForEach) 比 foreach 循环慢了大约 2 倍。

LINQ to SQL(MS SQL 数据库)几乎比使用数据读取器直接查询慢10 倍,大部分时间使用从表达式树创建 SQL(因此,您将受 CPU 限制并且数据库将处于空闲状态)为避免这种情况,您必须使用编译查询。

有关更多信息,请参阅此。帖子中的大多数信息对于 .NET 3.5 SP1 仍然有效。

于 2008-10-19T09:48:50.627 回答
9

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

让我们来谈谈 LINQ to 对象。一般而言,就大多数IEnumerable<T>迭代基础集合中的每个项目的实现而言,LINQ 具有很大的扩展潜力。创建一个List<Foo>包含一千万个项目的内容,如下所示:

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

会很慢。但这真的不是 LINQ 的错。是你给了它一千万个项目的清单。

如果 LINQ 不存在,您可以像处理它一样处理它:通过构建字典和 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 让它变得容易多了。

于 2008-10-18T00:44:00.963 回答
7

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

事实上,使用 LINQ 隐藏了很多复杂性,从而使事情变得如此简单,如果不负责任地使用它,可能会导致可伸缩性问题。

其他答案中的例子比比皆是,但最重要的是:

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

  • 如果您使用 LINQ 自动生成 SQL,据我所知,您无法为数据库提供有关如何编译查询的提示,例如WITH (NOLOCK). 随着您的表大小增加,能够解决这些问题势在必行。

  • 与上述类似,但可能更通用:当您解决数据库的可伸缩性问题时,您必须控制数据库正在做什么。拥有一种可以编译为 SQL 的语言,然后再将其编译为执行计划,从而消除了您的控制权。

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

  • 尽管看起来很简单,但您无法轻松更改 LINQ 提供程序:查询 SQL Server 与查询对象或查询 XML 不同。LINQ 非常相似。我确实希望我的一些初级开发人员继续“LINQ 狂欢”,因为这比学习如何在考虑可伸缩性的情况下做事更容易。

总之,我认为可以使用 LINQ 编写可扩展的代码,但必须小心使用它。没有杀手级工具,只有杀手级代码

于 2008-10-19T10:19:12.673 回答
3

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

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

如果您关心 Speed 并且大量使用 LINQ to objects ,那么这里有一个 codeplex 项目(我认为),它可以为您提供 1000 倍的性能改进。

于 2008-10-18T00:20:21.043 回答
3

您在某些方面关于可伸缩性的问题取决于您使用 LINQ 的目的。在业务应用程序中,您不会发现很多 SQL 命令正在执行——它们很慢并且必须在 DBMS 中编译。相反,您将看到大量存储过程调用。这些在 LINQ 中会稍微快一些。

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

在横向扩展方面,如果您想稍微分发数据,或者您可以使用 SQL 服务器复制,您总是可以将 LINQ 放在 Web 服务后面。它的可扩展性不应低于 ADO.NET。

于 2008-10-18T00:36:13.523 回答
1

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

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

您经常会看到应该揭示一些结论性的微基准,但它们从未这样做,因为它们只是整个问题的关键洞。

您可以在此处提取旧的 20/80 示例。可能 20% 是关于工具的,80% 是关于构成应用程序的各种有形的东西。

于 2008-10-18T00:53:59.523 回答
1

如果您正在寻找一个现实生活中的示例,stackoverflow 大量使用 Linq,请查看此帖子/播客

于 2008-10-22T05:10:03.920 回答
1

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

如果所有目标的生命周期都很短,并且应用程序每次执行新工作时都会创建新的 DataContext,这不是问题。但是我可以看到,如果有人不知道每个对象都会带来额外的负担,它会如何产生可伸缩性问题。

于 2008-12-08T21:52:38.323 回答
0

Linq 在很多方面都是可扩展的。

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

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

于 2010-09-08T19:20:17.870 回答