2009-12-10 61 views
12

我想知道是否有这两个选项之间的真正性能增益:SQL加入VS在代码单独的查询,而不加入 - 性能

选项1:

  • 我做一个SQL查询与加入以选择所有用户及其等级。

选项2:

  • 我做一个SQL查询来选择所有用户
  • 我获取所有用户,做一套SQL查询来获取该用户的行列。

在代码中,选项二更容易实现。这只是因为我设计我的持久层的方式。

所以,我想知道对性能有什么影响。在考虑采取选项1而不是选项2的情况下,我应该考虑什么限制?

回答

12

一般而言,数据库服务器在加入时总是比应用程序代码快。请记住,您必须为每个连接执行一次额外的网络往返查询。但是,如果您的第一个结果集很小并且您的索引调整得很好,那么此模型可以正常工作。

如果你只是这样做来重新使用你的ORM解决方案,那么你可能正在为一场失败的战斗而战。我总是发现我需要只能使用SQL生成的只读数据集,所以现在我使用ORM进行每个对象的CRUD操作,并使用常规SQL进行搜索,报告,聚合等。

+0

往返是什么意思?好奇心,你用什么ORM? – Melursus 2009-12-10 21:53:30

+0

往返意味着从应用程序转到数据库服务器并返回。当你在应用程序中加入,你在一个循环中运行子查询,即在运行ñ额外查询/往返,它做的非常糟糕 – 2009-12-10 22:49:35

+0

没错。如果你的第一个查询总是要具有行的理智最大数(比如说,超级模特国际象棋冠军)和子表是速度快,小的(就像他们的孩子的名字),然后在应用程序中加入不具有大后果。如果联结很大或持续增长(所有客户和订单),那么在您转移到其他方面后,生产会变得很难看。 – 2009-12-11 17:48:16

0

这取决于您预计有多少用户。选项一定会更快,但有了合理数量的数据,差异将可以忽略不计。

+0

每天往返伤害,即使有只有10或20个用户,你正在做的比需要 – 2009-12-10 19:33:55

1

如果等级是静态值,请考虑将它们缓存到应用程序中。

如果您需要频繁使用用户并且排名很少,请考虑延迟加载排名。 (例如,单独的查询,但第二个查询仅偶尔使用)。

如果您总是需要这两组数据,那么它们必须是数据库的当前副本。

原型可能的选择,并运行性能测试。

编辑:关于你的持久层的进一步想法,因为我自己面对这个。考虑将处理连接的“持久性”类添加为基本查询,并且是只读的。这是否适合您的特定场景是由您决定的,但许多应用程序的很多数据库访问都基于联接,​​联接可能相当大且复杂。如果你能够以一致的方式处理这些持久的,可更新的对象,那么它对你的整体架构来说可能是一个巨大的胜利。从概念上来说,这很像是在数据库中查看视图,查询视图而不是编写联接,但是您在代码中完成所有工作。

+0

你有你的“Persitence状”类的一些例子或链接大量的工作? – Melursus 2009-12-10 21:55:31

+0

没有什么我可以在线发布,因为他们还没有写!我编写了实体类,其行为与LINQ to SQL实体非常相似,但是由“经典”ADO.NET代码填充。我也有活动记录类封装表级查询和数据访问代码,并生成INSERT和UPDATE语句。 Active Record类从DataSet中填充实体。实体类包含支持ActiveRecord函数的元数据。我们将在未来使用代码生成器来构建这些代码。相同的结构应该适用于复杂的查询。希望我可以使用LINQ,但我不能。 – 2009-12-10 22:36:42

0

在99%的情况下,加入会更快。

但是有一种情况可能会比较慢。如果您正在进行一对多的大行连接,并且您正在达到网络带宽限制。

例如有在1MB大小的T1 BLOB列,要加入T2其由100行对于每个T1行。结果集将是T1行计数倍数100.

所以,如果你正在查询一个T1行加入它将是100MB的结果集,如果你取T1行(1MB),然后做单独的选择以获取100 T2的这个T1的结果集将为1MB。