【问题标题】:SQL Join vs Separate Query in Code without Join - PerformanceSQL 连接与没有连接的代码中的单独查询 - 性能
【发布时间】:2010-12-25 09:28:34
【问题描述】:

我想知道这两个选项之间是否真的有性能提升:

选项 1:

  • 我使用连接执行 SQL 查询以选择所有用户及其排名。

选项 2:

  • 我执行一个 SQL 查询来选择所有用户
  • 我获取所有用户并执行另一个 SQL 查询以获取此用户的排名。

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

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

【问题讨论】:

    标签: sql performance join


    【解决方案1】:

    一般来说,数据库服务器在加入时总是比应用程序代码快。请记住,对于每个连接,您都必须使用网络往返进行额外查询。但是,如果您的第一个结果集很小并且您的索引经过良好调整,则此模型可以正常工作。

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

    【讨论】:

    • 往返是什么意思?出于好奇,您使用的是什么 ORM?
    • 往返意味着从应用程序到数据库服务器再返回。当您加入应用程序时,您正在循环运行子查询,即您运行 N 个额外的查询/往返,这非常糟糕
    • 没错。如果你的第一个查询总是有一个合理的最大行数(比如,超级模特国际象棋冠军),并且子表又快又小(比如他们孩子的名字),那么加入应用程序并没有很大结果。如果联接很大或不断增长(您的所有客户及其订单),在您转移到其他事情之后,这可能会在生产中变得丑陋。
    • 我们在 Cold Fusion 和 Myna (mynajs.org) 中开发。对于 CF,我们使用从表元数据生成 DAO 的本土解决方案,在 Myna 中,我们使用 Myna 的运行时 ORM 解决方案。在这两种情况下,我们使用额外的函数扩展生成的对象,这些函数在 SQL 中执行更复杂的查询,并从持久层返回结构化数据或 DAO 数组。对于更复杂的对象,我们使用惰性绑定组合多个 DAO。
    • 这个好的答案将您引向 CQS 模型(命令-查询分离),其中 ORM 对象用于 CRUD,独立查询用于查看和报告。
    【解决方案2】:

    如果排名是静态值,请考虑将它们缓存在您的应用程序中。

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

    如果您总是需要两组数据,并且它们必须是数据库的当前副本,请使用联接。

    对任何可能的选择进行原型设计,并运行性能测试。

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

    【讨论】:

    • 你有一些关于你的“Persitence-like”类的例子或链接吗?
    • 我无法在网上发布任何内容,因为它们还没有写出来!我编写了实体类,其行为与 LINQ to SQL 实体非常相似,但由“经典”ADO.NET 代码填充。我也有封装表级查询和数据访问代码并生成 INSERT 和 UPDATE 语句的 Active Record 类。 Active Record 类从 DataSet 中填充实体。实体类包含支持 ActiveRecord 功能的元数据。我们将在未来使用代码生成器来构建这些。相同的结构应该适用于复杂的查询。希望我可以使用 LINQ,但我不能。
    【解决方案3】:

    这取决于您预期的用户数量。选项一肯定会更快,但在数据量合理的情况下,差异可以忽略不计。

    【讨论】:

    • 每次往返都会很痛苦,即使只有 10 或 20 个用户,您所做的工作也比需要的多得多
    【解决方案4】:

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

    但是,在极少数情况下它可能会变慢。如果您正在对具有大行大小的表进行一对多联接,并且您正在达到网络带宽限制。

    例如,在 T1 中有一个大小为 1MB 的 blob 列,您将加入 T2,该列由每个 T1 行 100 行组成。结果集将是 T1 行数的 100 倍。

    因此,如果您使用连接查询一个 T1 行,则结果集将是 100MB,如果您获取 T1 行 (1MB),然后单独选择以获取该 T1 的 100 个 T2,则结果集将为 1MB。

    【讨论】:

      猜你喜欢
      • 2011-04-20
      • 1970-01-01
      • 1970-01-01
      • 2016-08-19
      • 2019-08-06
      • 1970-01-01
      • 2021-07-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多