我们正在使用Oracle 11,我们的应用程序是用Java编写的。每天一次,通常是下午我们的数据库冻结因为许多大的SQL查询。我想以某种方式优化这些查询。此查询包含许多不同表的连接。我的问题是:使用左连接是否更好的性能,或者最好将所有信息放在一个表中并使用一个选择?假设我将为此表构建一个好的索引。
有关信息:平均而言,一个查询获取100兆字节。此查询有时会相互锁定
更新
连接8个表的表,它们是3-5列的常用表,其中一列是一些ID。 Sql查询看起来像:
SELECT t1.c1,t2.c5, t6.c2, ... FROM t1
LEFT JOIN t2 ON t1.c1 = t2.c1
LEFT JOIN t3 ON t3.c1 = t2.c2
LEFT JOIN t4 ON t4.c1 = t2.c1
LEFT JOIN t5 ON t5.c5 = t1.c1
LEFT JOIN t6 ON t6.c1 = t2.c1
LEFT JOIN t7 ON t7.c3 = t3.c1
LEFT JOIN t8 ON t8.c1 = t2.c1
WHERE something
我的问题是,最好是创建一个包含所有连接表的新表,并使用如下查询:
SELECT c1,c5, c2, ... FROM SOME_NEW_TABLE
更新2
以下是report,如果有人可以解释一般情况,那就太棒了。
答案 0 :(得分:5)
我认为这个问题可以得到普遍回答。在性能调优这种类型的查询中,您需要考虑以下几点:
为声明建立执行计划需要多长时间?如果查询第一次运行缓慢并且以后快速运行,则解析时间是个问题。我假设查询中没有更改常量。如果没有,请使用绑定变量或作为最后的手段使用动态绑定变量,但我自动引入绑定变量可能是一个坏主意,请参阅“alter session set cursor_sharing = similar”。
特别是对于旧版本和许多连接(Oracle 8在解析具有超过6个类似身份连接的语句时非常糟糕......)解析时间可能很昂贵。 Oracle 11通常会在考虑了许多执行计划后停止,从而缩短解析时间。在Oracle 11上,解析时间仍然是一个问题,特别是对于union / union all。
此外,在此查询中,您使用ANSI样式连接。请注意,当使用更复杂的ANSI样式连接与复杂语句时,Oracle 11具有一些性能缺陷。因此,对于自动生成的语句,我建议使用Oracle样式(c(+)= d),对于需要维护的语句,您需要研究它是否确实存在问题。
当解析时间有问题时,我建议使用/ * + ordered * /这样的提示作为起点。这样可以确保您的连接顺序是这样的,即临时生成的数据量尽可能少,并且存在正确的索引。
在执行期间,Oracle执行执行计划。与其他数据库平台相比,Oracle确实非常有效。但是如果执行计划很糟糕,执行需要时间。在你的问题中,你谈论是否要加入一切。
一般情况下,最好始终使用完全标准化的模型。在完全标准化的模型中,数据仅存储一次。因此,当有效地规划查询时,处理的数据量最少。这假设Oracle服务器有足够的内存来缓存它的全部或大部分,因为连接策略有时需要内存中的大量工作空间以及已经从磁盘中获取的数据。
当表现不足时,我会首先介绍提示,但要遵循规范化模型。始终尽量保持在临时步骤中符合输出要求的数据量。当它真的不起作用时,你可能会选择派生表,但我发现这通常表明开发技能很弱。
在所有这些中,我假设启动执行计划的其中一个表具有较大的数据量而另一个表较小,可能稍微小一点或小一些。如果没有,你正在运行一个“Wiebertje”查询(我没有其他名称,它是荷兰糖果的形状)。那么请阅读第9页以及conference presentation 2006
的更多内容在周期结束时,Oracle会在某个时刻开始发回数据。特别是音量可以高度传输所需的时间。应用程序绝对获取所有内容并且只显示前50行并不罕见。请介绍窗口或“获取显示的水印+常量”以减少获取时间。您可能需要在语句或会话中引入一个提示,例如/ * + first_rows * /以供交互使用。