我有一个巨大的 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;
任何人都可以建议如何处理性能问题或我可以使用的任何编程技术。
我尝试添加此表,其中所有表都已连接,但由于此表中的一对多映射,结果受到影响
我们不可能向您指出您可能遇到的每个问题,因为您没有向我们展示真正的查询、执行计划或有关表大小的任何信息。性能调优是一项复杂的工作,需要将多条信息放在一起,而这些信息在像 SO 这样的论坛中不容易沟通。
但是,您所所显示的内容在许多(不是全部)情况下可能会出现问题,因为:
select B,
(select B from A where condition1),
(select B from A where condition2),
--and so on(65 more times)
from
您有 67 个单独的子查询嵌套在主块的
SELECT
子句中。这有几个问题:
从历史上看,优化器必须对父块中的每一行执行这些操作,这意味着它强制
nested loops
连接。这需要仔细的索引,即使索引正确,如果主块中的行数过多,这些子查询的所有单个块读取的开销也会增加并成为瓶颈。最近版本的 Oracle 已经开始能够重写这种错误的查询模式并将其转换为正常连接,因此可以使用 hash
连接来代替。但这并不总是发生,并且以这种方式编写时很难控制。这个故事的寓意是:要非常谨慎地使用 SELECT
子句中的内联选择。 FROM
子句中的普通连接几乎总是更好的模式。
其中 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 次。
同样,您的查询可能还有很多其他问题,但这是需要根据您与我们分享的内容进行调查的内容。