为什么此查询的性能优于ANSI JOIN版本?

时间:2016-10-06 16:13:32

标签: oracle performance

我一直在努力提高这个查询的性能一段时间,在尝试了多种不同的方法后,我发现删除ANSI JOIN并使用传统语法可以根据解释计划显着降低成本(459928 vs. 82518117)。这是原始的(剪裁和修剪):

select distinct api.locn_id         -- Explain Plan: 82518117
                 ,i.item_set_id
                 ,api.variant_id
    from all_planogram_items api
    join includes i
      on api.variant_id = i.variant_id
      or api.dept_id = i.dept_id
      or api.category_id = i.category_id
      or api.fixture_id = i.fixture_id
      or api.aisle_id = i.aisle_id
   where 1 = 1
     and /* variant is not in excludes list*/
        --e.item_set_id is null
         not exists
... etc

以及传统联接的更好表现:

select distinct api.locn_id        -- Explain Plan: 459928
                 ,i.item_set_id
                 ,api.variant_id
    from all_planogram_items api, includes i
   where 1 = 1
     and (api.variant_id = i.variant_id
      or api.dept_id = i.dept_id
      or api.category_id = i.category_id
      or api.fixture_id = i.fixture_id
      or api.aisle_id = i.aisle_id)
     and /* variant is not in excludes list*/
        --e.item_set_id is null
         not exists
... etc

就像我提到的,这个查询还有更多内容(内联视图等),但我所做的唯一更改就是在连接上。我觉得它与or条款有关,但我自己无法解释。为什么这样效率更高?

更多信息:

  • 查询确实运行得更快(大约快两倍),这不仅仅是计划成本。
  • 两个查询都返回完全相同的结果
  • 每个查询的附加执行结果相同; ANSI JOIN大约是传统连接的两倍。
  • 我们使用的是Oracle Database 11g企业版11.2.0.4.0 - 64位

以下是解释计划。我想重新讨论这些解释计划的唯一区别是上面解释的连接方法。奇怪的是,较低的成本和更快的传统JOIN解释计划是慢速ANSI JOIN解释计划的3倍(对于屏幕截图,解释计划太大,无法在此处发布文本版本):

传统的JOIN解释计划:

  1. http://i.stack.imgur.com/ocgOs.png
  2. http://i.stack.imgur.com/zbdOe.png
  3. http://i.stack.imgur.com/lVyQk.png
  4. ANSI JOIN解释计划:

    1. http://i.stack.imgur.com/HtjUm.png

3 个答案:

答案 0 :(得分:2)

  

为什么这样效率更高?

你的一个计划可能正在进行OR扩展,另一个可能不是。

Oracle转换ANSI连接语法查询的逻辑并不完美,与转换非ANSI连接语法查询的逻辑不完全相同。如果您将在Oracle的支持网站上查看补丁,您会发现几乎每个版本都有许多错误修正。

答案也延伸到其他领域。例如,在某些Oracle版本中,如果将其放入SELECT语句或INSERT语句中,则可以使用快速运行的CREATE TABLE AS SELECT语句。

Oracle连接和ANSI连接在概念上是相同的,应该没有区别。但是,实际上存在差异。

答案 1 :(得分:0)

解释计划成本通常不是衡量绩效的好方法。对于类似的查询,它可能会有所不同,并且不会影响性能。您可能需要查看autotrace统计信息和tkprof以获得更多信息。另请参阅this link

答案 2 :(得分:0)

如果您使用SQL Developer或Toad(他们有一个直接向您显示执行计划的按钮),您可以轻松查看每个查询的解释计划。最好比较一下计划,看看,例如,由于复杂的ON条件,优化器没有“看到”将谓词从连接推送到组件表或视图的机会。将条件移动到WHERE子句允许优化器以不同的顺序(可能)查看过滤器并查看此类机会。这可能是完全错误的,但它通过查看解释计划显示了您可能会注意到的事情。