【问题标题】:Performance: Subquery or Joining性能:子查询或加入
【发布时间】:2011-02-21 17:30:45
【问题描述】:

我有一个关于子查询性能/加入另一个表的小问题

INSERT
INTO Original.Person
  (
    PID, Name, Surname, SID
  )
  (
    SELECT ma.PID_new , TBL.Name , ma.Surname, TBL.SID 
    FROM Copy.Person TBL , original.MATabelle MA
    WHERE TBL.PID         = p_PID_old
      AND TBL.PID         = MA.PID_old
  );

这是我的 SQL,现在这个东西运行了大约 100 万次或更多。 我的问题是什么会更快?

  • 如果我将 TBL.SID 更改为 (Select new from helptable where old = tbl.sid)

  • 如果我将“HelpTable”添加到from 并加入where

编辑1
好吧,这个脚本只运行 r 人。

我的程序有 2 个模块,一个用于填充 MaTabelle,另一个用于传输数据。该程序确实将 2 个数据库合并在一起,因此有时会使用相同的密钥。
现在我正在研究一个不存在重复键的解决方案。

我的解决方案是制作一个“帮助表”。密钥的所有者 (SID) 生成一个新密钥并将其写入“HelpTable”。使用此键的所有其他表都可以从“HelpTable”中读取它。

edit2
突然想到了什么:
如果一个表作为一个可以为空的键(未链接的外键) 那么这不适用于 from or 吗?

【问题讨论】:

    标签: sql oracle


    【解决方案1】:

    加入会比子查询快得多

    【讨论】:

    • 因为有子查询,所以会先创建一个临时表,然后再加入。
    【解决方案2】:

    子查询和连接之间的主要区别是 当我们必须从大量表中检索数据时,子查询会更快。因为连接更多表变得乏味。 当我们的表数量较少时,join 可以更快地从数据库中检索数据。

    另外,这个joins vs subquery 可以为您提供更多信息

    【讨论】:

      【解决方案3】:

      包括 Oracle 在内的现代 RDBM 将大多数连接和子查询优化到相同的执行计划。

      因此,我会继续以对您来说最简单的方式编写您的查询,并专注于确保您已完全优化索引。

      如果您提供最终查询和数据库架构,我们或许能够提供详细的建议,包括有关潜在锁定问题的信息。

      编辑

      以下是一些适用于您的查询的一般提示:

      • 对于连接,请确保您在要连接的列上有一个索引。请务必将索引应用于两个表中的连接列。您可能认为您只需要一个方向的索引,但您应该同时索引两个方向,因为有时数据库会确定最好加入相反的方向。
      • 对于 WHERE 子句,确保您对 WHERE 中提到的列有索引。
      • 要插入多行,最好将它们全部插入到一个查询中。
      • 要在具有聚集索引的表上插入,最好使用聚集索引的增量值插入,以便将新行附加到数据的末尾。这避免了重建索引,并且通常避免了对现有记录的锁定,这会减慢对现有行的 SELECT 查询。基本上,插入对系统的其他用户来说变得不那么痛苦了。

      【讨论】:

      • 很好地提供我的数据库模式是不可能的,因为它有大约 100 个或更多的表,而且很难理解。我现在看看我要做什么。
      • 我们不需要您的整个架构,只需要查询中引用的表。
      • 现在使用子查询更容易,感谢您的帮助。
      【解决方案4】:

      我不会关注是否使用联接或子查询,而是关注执行该特定插入语句的 1,000,000 次的必要性。尤其是 Oracle 的优化器 - 正如 Marcus Adams 已经指出的那样 - 将在幕后优化和重写您的语句,使其达到最佳形式。

      您是否仅用几行填充 MaTabelle 1,000,000 次并发出该语句?如果是,那么答案是一次性完成。您能否提供更多关于您的进程多次执行此语句的信息?

      编辑:你指出这个插入语句是为每个人执行的。在这种情况下,建议是先填充 MATabelle,然后执行一次:

      INSERT 
      INTO Original.Person 
        ( 
          PID, Name, Surname, SID 
        ) 
        ( 
          SELECT ma.PID_new , TBL.Name , ma.Surname, TBL.SID  
          FROM Copy.Person TBL , original.MATabelle MA 
          WHERE TBL.PID         = MA.PID_old 
        );
      

      问候, 抢。

      【讨论】:

        猜你喜欢
        • 2016-10-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-13
        • 2015-01-17
        • 1970-01-01
        • 2014-11-14
        • 1970-01-01
        相关资源
        最近更新 更多