【问题标题】:What is better/faster: joining many tables or select one big table什么更好/更快:加入多张桌子或选择一张大桌子
【发布时间】:2013-12-11 22:29:18
【问题描述】:

我们使用的是 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,如果有人能概括地解释一下就好了。

【问题讨论】:

  • 这个问题太宽泛,无法在这里回答,没有具体细节。进行一些分析、运行 Statspack、查看 SGA、运行解释计划等。我们对您的表及其关系一无所知。
  • 感谢有关 Statspack 的建议,我会尝试的。我有使用 utlestat、utlbstat 的 report.txt。但我不理解 90% 的报告信息。如果你能解释一下这份报告的一些内容,我可以在这里粘贴一些部分。
  • 如果您发布报告,那么也许可以解释。您必须发布确切的查询及其执行计划,以获得优化它们的建议。

标签: database performance oracle join oracle11g


【解决方案1】:

我认为这个问题一般可以回答。在调整此类查询的性能时,您需要考虑许多事项:

解析时间

为语句建立执行计划需要多长时间?如果查询第一次运行缓慢而以后一直运行快速,则解析时间是一个问题。我假设查询中没有变化的常量。如果没有,请使用绑定变量或作为最后的手段使用动态绑定变量,但自动引入绑定变量可能不是一个好主意,请参阅“alter session set cursor_sharing=similar”。

尤其是旧版本和许多连接(Oracle 8 在解析具有超过 6 个相似标识连接的语句时非常糟糕......)解析时间可能很昂贵。 Oracle 11 通常通过在考虑了多个执行计划后停止来缩短解析时间。在 Oracle 11 上,解析时间仍然可能是一个问题,尤其是使用 union/union all。

此外,在此查询中,您使用 ANSI 样式连接。请注意,Oracle 11 在使用更优雅的 ANSI 样式连接复杂语句时存在一些性能缺陷。对于自动生成的语句,我因此推荐Oracle风格(c(+)=d),对于需要维护的语句,你需要研究它是否真的有问题。

当解析时间成为问题时,我建议使用 /*+ ordered */ 之类的提示作为起点。这样可以确保您的连接顺序使得临时生成的数据量尽可能少并且存在正确的索引。

执行时间

在执行期间,Oracle 执行执行计划。与其他数据库平台相比,Oracle 确实做到了这一点。但是如果执行计划很糟糕,执行需要时间。在您的问题中,您谈论是否要预先加入所有内容。

一般来说,最好总是从完全标准化的模型开始。在完全标准化的模型中,数据只存储一次。因此,当查询得到有效计划时,处理的数据量最少。这假设 Oracle 服务器有足够的内存来缓存它的全部或大部分,因为连接策略有时需要内存中的大量工作空间以及已经从磁盘获取的数据。

当性能不足时,我会从引入提示开始,但仍使用规范化模型。始终尽量保持在中间步骤中符合输出条件的数据量尽可能小。当它真的不起作用时,您可能会使用派生表,但我发现这通常表明开发技能较弱。

在这一切中,我假设启动执行计划的表中的一个数据量很大,而另一个较小,可能小一点或小很多。如果没有,您正在运行“Wiebertje”查询(我没有其他名称,它是荷兰糖果的形状)。那么请阅读第 9 页及更多 conference presentation 2006

获取时间

在循环结束时,Oracle 在某个时刻开始发回数据。尤其是音量可以很长的时间来转移它。应用程序获取绝对所有内容的情况并不少见,但只显示前 50 行。请引入窗口或“提取到显示的水印+常量”以减少提取时间。您可能需要在语句或会话中引入诸如 /*+ first_rows */ 之类的提示以供交互使用。

【讨论】:

    猜你喜欢
    • 2011-05-04
    • 2011-11-17
    • 2018-04-09
    • 2017-02-07
    • 2011-09-25
    • 1970-01-01
    • 2014-01-24
    • 2012-05-23
    • 2019-02-25
    相关资源
    最近更新 更多