生产中有一个查询,运行了几个小时(5-6)小时。我查看了它的执行计划,发现它忽略了一张巨大的桌子上的平行提示。原因 - 它使用了TABLE ACCESS BY INDEX ROWID。因此,在*+ full(huge_table) */
提示之前添加/ parallel(huge_table)
提示后,查询开始并行运行,并在不到3分钟内完成。我无法理解的是这种巨大性能差异的原因。
以下是我能想到的并行FTS的优点:
当然有上述优点,但仍有以下缺点:
有了上述知识,我发现只有一个原因可能导致查询在使用ACCESS BY INDEX ROWID时出现性能不佳 - 某种争用类似“忙缓冲等待”。但它没有出现在AWR前5名的等待事件中。前两个事件是“db file sequential read”和“db file scattered read”。还有其他我错过的东西需要考虑吗?请赐教。
答案 0 :(得分:6)
首先,我不知道你的数据量,统计数据,谓词的选择性等等。我猜你所看到的主要好处是进行表扫描而不是尝试使用索引。索引不一定快,表扫描不一定很慢。如果您使用索引中的rowid来访问行,那么Oracle仅限于执行单个块读取(以Oracle术语进行顺序读取),并且如果块具有多次读取,则必须多次读取相同的块很多感兴趣的行。另一方面,全表扫描可以进行漂亮,高效的多块读取(Oracle术语中的分散读取)。当然,单个单块读取比单个多块读取更有效,但多块读取每字节读取效率更高。此外,如果您正在使用索引,则可能需要定期从索引中读取多个块,以找出要从表中读取的下一个rowid。
在表扫描比索引更有效之前,您实际上并不需要从表中读取所有那么多数据。根据许多其他因素,临界点可能在10-20%的范围内(这是一个非常非常粗略的猜测)。想象一下,您必须从电话簿中获取一堆名称,并且电话簿中包含一个索引,其中包含您要过滤的信息以及该条目所在的页面。您可以使用索引查找要查看的单个人的姓名,翻到指示的页面,记录信息,翻回索引,找到下一个名字,翻回等等。或者您可以简单地开始以第一个名称扫描,直到找到感兴趣的名称,记录信息并继续扫描。在您最好忽略索引并从表中读取之前,它不会花太长时间。
添加并行性并不会减少查询的工作量(实际上,添加并行查询协调意味着您正在做更多的工作)。只是通过使用更多服务器的可用资源,您可以在较短的时间内完成该工作。如果您使用6个并行从属运行查询,那么这当然可以使查询总体运行速度提高5倍(并行查询显然比由于开销而线性缩小一点)。如果是这种情况,那么您预计进行表格扫描会使查询速度提高20倍,并且添加并行度会增加另一个因子5以获得100倍的提升。