【问题标题】:Oracle 10g Full table scan(parallel access) 100x times faster than index access by rowidOracle 10g 全表扫描(并行访问)比 rowid 索引访问快 100 倍
【发布时间】:2014-09-18 22:45:34
【问题描述】:

生产中有一个查询运行了几个小时 (5-6) 小时。我查看了它的执行计划,发现它忽略了一张大桌子上的并行提示。原因 - 它使用索引 ROWID 的表访问。因此,在我在parallel(huge_table) 提示之前添加 /*+ full(huge_table) */ 提示后,查询开始并行运行,不到 3 分钟就完成了。我无法理解的是造成这种巨大性能差异的原因。 以下是我能想到的并行 FTS 的优点:

  1. 如果您有更多空闲 CPU,并行操作本质上会很快。
  2. 10g 中的并行操作是绕过的直接 I/O 缓冲区缓存,这意味着没有“缓冲区忙等待”的风险或 缓冲区缓存的任何其他争用。

当然有上面的优点,但是下面的缺点仍然存在:

  1. 并行操作仍然需要进行 I/O,并且此 I/O 将比我们通过索引 ROWID 访问表所拥有的更多,因为整个表都被扫描并且成本更高(所有物理读取)
  2. 并行操作的可扩展性不是很好,这意味着如果没有足够的可用资源,它会很慢

有了以上知识,我看到只有一个原因可能导致查询在使用 ACCESS BY INDEX ROWID 时性能不佳 - 某种争用,例如“缓冲区忙等待”。但它没有出现在 AWR 前 5 个等待事件中。前两个事件是“db 文件顺序读取”和“db 文件分散读取”。还有什么我没有考虑到的吗?请赐教。

【问题讨论】:

  • 执行计划是否包含操作“BITMAP CONVERSION TO ROWIDS”?
  • @mmdw:不。该计划不包含该操作

标签: sql performance oracle parallel-processing oracle10g


【解决方案1】:

首先,不了解您的数据量、统计信息、谓词的选择性等。我猜您看到的主要好处是进行表扫描而不是尝试使用索引。索引不一定很快,表扫描也不一定很慢。如果您使用索引中的 rowid 来访问行,Oracle 仅限于执行单块读取(Oracle 术语中的顺序读取),并且如果块有很多感兴趣的行,它将不得不多次读取同一个块.另一方面,全表扫描可以进行良好、高效的多块读取(Oracle 术语中的分散读取)。当然,单个单块读取将比单个多块读取更有效,但多块读取每个字节读取的效率要高得多。此外,如果您使用索引,则可能需要定期从索引中读取多个块,以找出要从表中读取的下一个 rowid。

在表扫描比索引更有效之前,您实际上不需要从表中读取所有数据。取决于许多其他因素,临界点可能在 10-20% 的范围内(这是一个非常非常粗略的猜测)。想象一下,您必须从电话簿中获取一堆姓名,并且电话簿有一个索引,其中包含您要过滤的信息和条目所在的页面。您可以使用索引找到您想查看的单个人的姓名,翻到指示的页面,记录信息,翻回索引,查找下一个姓名,翻回等。或者您可以简单地开始在第一个名称处扫描,直到找到感兴趣的名称,记录信息,然后继续扫描。用不了多久,您最好忽略索引并只从表中读取数据。

添加并行性不会减少查询的工作量(事实上,添加并行查询协调意味着您正在做更多的工作)。只是您通过使用更多服务器的可用资源在更短的时间内完成了这项工作。如果您使用 6 个并行从属服务器运行查询,那肯定可以使查询整体运行速度提高 5 倍(由于开销,并行查询显然比线性扩展要小一些)。如果是这种情况,您会期望执行表扫描可使查询速度提高 20 倍,而添加并行性又增加了 5 倍,从而获得 100 倍的改进。

【讨论】:

  • "单块读取(Oracle 术语中的顺序读取)和...高效的多块读取(Oracle 术语中的分散读取)" -- 你确定不是另一个怎么办?
  • @mustaccio - 是的。 Oracle 术语与您可能直观地期望的相反 hotsos.com/e-library/abstract.php?id=16
  • 谢谢。找到another interesting read,也有图片。看来Oracle也重新定义了“直接I/O”的含义……
猜你喜欢
  • 2016-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-01
  • 1970-01-01
  • 2015-01-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多