提高Oracle中sql查询的性能

问题描述 投票:0回答:1

我有一个巨大的 SQL 查询,其结构如下,由于一对多映射,并且在 sql 语句中出现了 67 次表,所以使用同一个表。

SQL结构 :假设我们有表 A(列:B、C、D、E),

select B,
       (select B from A where condition1),
       (select B from A where condition2),
       --and so on(65 more times)
from   table joins
where  cond3;

任何人都可以建议如何处理性能问题或我可以使用的任何编程技术。

我尝试添加此表,其中所有表都已连接,但由于此表中的一对多映射,结果受到影响

oracle query-optimization
1个回答
1
投票

我们不可能向您指出您可能遇到的每个问题,因为您没有向我们展示真正的查询、执行计划或有关表大小的任何信息。性能调优是一项复杂的工作,需要将多条信息放在一起,而这些信息在像 SO 这样的论坛中不容易沟通。

但是,您所显示的内容在许多(不是全部)情况下可能会出现问题,因为:

select B,
       (select B from A where condition1),
       (select B from A where condition2),
       --and so on(65 more times)
from 

您有 67 个单独的子查询嵌套在主块的

SELECT
子句中。这有几个问题:

  1. 从历史上看,优化器必须对父块中的每一行执行这些操作,这意味着它强制

    nested loops
    连接。这需要仔细的索引,即使索引正确,如果主块中的行数过多,这些子查询的所有单个块读取的开销也会增加并成为瓶颈。最近版本的 Oracle 已经开始能够重写这种错误的查询模式并将其转换为正常连接,因此可以使用
    hash
    连接来代替。但这并不总是发生,并且以这种方式编写时很难控制。这个故事的寓意是:要非常谨慎地使用
    SELECT
    子句中的内联选择。
    FROM
    子句中的普通连接几乎总是更好的模式。

  2. 其中 67 个?对于 any 连接模式来说,表数量过多。 SQL 查询不应涉及那么多表。如果我能猜到的话,我敢打赌您不会访问 67 个不同的表,而是一遍又一遍地访问同一个表,每次都会得到不同的列。如果是这样的话,那么我们重写一下:

    2a。如果您不使用聚合(连接键在另一个表上是唯一的),只需正常连接即可:

    SELECT a.col1,
           a.col2,
           b.col1,
           b.col2,
           b.col3, etc..
      FROM tableA a
           LEFT OUTER JOIN tableB on a.fkid = b.pkid
    

    2b。但是,如果您正在进行聚合,则可以进行预聚合和散列连接,或者如果您想要嵌套循环操作,则使用

    OUTER APPLY

    SELECT a.col1,
           a.col2,
           b.col1,
           b.col2,
           b.col3, etc..
      FROM tableA a
           LEFT OUTER JOIN (SELECT pkid,
                                   MAX(col1) col1,
                                   MAX(col2) col2,
                                   SUM(col3) col3
                              FROM tableB
                             GROUP BY pkid) b on a.fkid = b.pkid
    

    或者

    SELECT a.col1,
           a.col2,
           bx.col1,
           bx.col2,
           bx.col3, etc..
      FROM tableA a
           OUTER APPLY (SELECT MAX(col1) col1,
                               MAX(col2) col2,
                               SUM(col3) col3
                          FROM tableB b
                         WHERE b.pkid = a.fkid) bx
    

最后一个模式的优点是它允许您执行嵌套循环操作(如果您只拉取一小部分

tableA
行,则很有用),同时拉回多个聚合列而不是仅一个。这样您只需敲击桌子一次,而不是 67 次。

同样,您的查询可能还有很多其他问题,但这是需要根据您与我们分享的内容进行调查的内容。

© www.soinside.com 2019 - 2024. All rights reserved.