【问题标题】:How to make my query more efficient?如何让我的查询更有效率?
【发布时间】:2014-05-30 09:56:18
【问题描述】:

我正在使用 Toad 在 Oracle SQL 环境中运行查询,在该环境中我通过连接 16 个不同的表来构建表,但我的临时表空间已用完,我希望能就如何提高查询效率获得一些建议。我没有这方面的背景,所以我不确定最好的方法是使用中间表还是更改我的联接顺序。

主要有两个表,Header 和 Detail,header 有 2600 万行,detail 有 1.75 亿行。我对这些表使用内部联接,这将产生 1.75 亿行。其他 14 个表是较小的描述表,我使用左连接进行连接。其中三个表的行数为 350k 或更少,其他 11 个表的行数不到 1,000 行。我目前的伪代码如下:

    create table END_TABLE as
    select *
    from Detail
    inner join Header
    left join description_table_1
    left join description_table_2
    left join description_table_3
    left join description_table_4
    left join description_table_5
    left join description_table_6
    left join description_table_7
    left join description_table_8
    left join description_table_9
    left join description_table_10
    left join description_table_11
    left join description_table_12
    left join description_table_13
    left join description_table_14;

既然我是从我的详细信息表开始,然后加入页眉,那么效率会比我反过来做吗?我假设因为它是一个内部连接,所以没关系,但就像我之前所说的,我对提高查询效率不是很了解。

我的想法是创建一个单独的表,将标题和详细信息连接在一起,然后创建一个最终表,在其中加入较小的详细信息表。这会有帮助吗?更改我的加入顺序会有帮助吗?

【问题讨论】:

  • 有索引吗?
  • @johnny,没有索引
  • 您将需要在每个连接上都有一个 ON 或 USING 子句。您是否有可能限制行数的 WHERE 子句?我非常怀疑将标题放在细节之前或将细节放在标题之前会很重要。祝你好运。
  • 我知道我需要一个 ON 来进行连接,但我没有看到添加键对伪代码有什么帮助,但它们无法更改。没有 WHERE 标准。

标签: sql database oracle toad


【解决方案1】:

您正在将一个包含 1.75 亿行的表与另一个包含 2600 万行的表连接起来,该表没有索引,也没有 where 子句。

您需要索引。没有它们,你只是在泰坦尼克号的躺椅上晃来晃去。

【讨论】:

  • 并非总是如此,这取决于上下文。有许多系统可以连接数十亿行,并且在没有索引的情况下工作得最好。
  • @JonEarles - 您能否提供一个没有索引的情况下性能更好的示例?有时最好通过表扫描来处理 where 子句,但我从未见过在没有索引的情况下可以更好地处理连接的真实实例。
  • 这是一个简单的例子: 1.create table t as select * from dba_objects; 2.create index i on t(object_id); 3.select /*+ index(t1) index(t2) */ distinct t1.owner,t2.owner from t t1 join t t2 using (object_id); 4.alter system flush buffer_cache; 5.select /*+ no_index(t1) no_index(t2) */ distinct t1.owner,t2.owner from t t1 join t t2 using (object_id); 索引在包含所有查询数据或它们仅用于检索一小部分数据。这涵盖了几乎所有 OLTP 查询,但不适用于许多数据仓库查询。
【解决方案2】:

指数很可能无济于事:

当您完全连接两个表时,Oracle 很可能会对两个表进行 FULL TABLE SCAN,使用 HASH JOIN,并且不会考虑使用索引。

您可以尝试对 Header 和 Detail 表进行分区,然后在循环中一次加入一个分区并将结果插入 END_TABLE 表中。

【讨论】:

    【解决方案3】:

    根据我在 Oracle 11g 上的经验,当我处理大型表的许多联接时,我发现在每个步骤中使用具有较少联接的中间表通常会大大加快处理速度(在一种情况下,一步需要 7 小时)在多个步骤中花费了大约 20 分钟)。可能我会将 Detail 和 Header 连接到一个表中,然后一次将这个中间表与 1-3 个描述表连接起来,然后开始组合那些进一步的中间表。您说您没有索引:即使您没有排除 where 约束中的任何数据,我也希望索引能够加快连接速度。也许您不能在主表上建立索引,但如果您走这条路,您可能可以为中间表建立索引。请记住,您需要考虑是否在整个查询系列中维护一个事务,以防数据发生变化。

    【讨论】:

    • 中间表可能有帮助,但创建中间结果集是优化器应该透明地为您做的事情。最好弄清楚为什么 Oracle 没有正确构建这些中间结果集。
    【解决方案4】:
    • 如果您的最大数据量约为表中数据的 100%(根据您的描述),那么您不需要索引 - FTS 就可以正常工作。
    • 我不是 ANSI SQL 的忠实拥护者,我更喜欢使用“正确的工具来完成正确的任务”——并且使用 Oracle SQL 语法而不是 ANSI,但您似乎没有为连接指定列。据我回忆,只有在使用 NATURAL JOIN - WIKI 时才需要列。 JOIN 的所有其他情况都需要定义哪些列是参与者。
    • 列规范也与 LEFT JOIN (LEFT OUTER JOIN) 相关 - again

    【讨论】:

      猜你喜欢
      • 2015-01-24
      • 2016-03-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-08
      • 2021-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多