【问题标题】:Oracle optimizer hints xmlagg functionOracle 优化器提示 xmlagg 函数
【发布时间】:2015-11-20 08:15:59
【问题描述】:

我有一个函数,它使用一些 xmlaggs 数据调用多个表/视图等。

由于某种原因,当我提取额外信息时,即使这些额外信息没有用于其余代码(例如再次使用的键值的索引),我也会获得性能提升。

我已经在快速和慢速查询上运行了 tkprof,但我发现了一些问题 - 第一个是慢速查询在解析和执行期间有遗漏,而快速查询没有。

我的主要问题是,再往下看,我可以看到我的一个视图的成本很高 - 较快的查询使用基础表上的 3 个索引,而较慢的查询没有使用任何索引。

我已尝试插入提示:

SELECT /*+ index(view_alias,table1_index, table2_index, table3_index) */     
XMLCONCAT (...

但它仍在进行全表扫描。我是否将优化器提示放在错误的位置或为此使用了错误的语法?

编辑 - 我一直在做更多调查,看来这可能是 Oracle 进行哈希连接而不是嵌套循环的敲门声,但是我的选择来自多个表 - 我可以在所有 3 个表上强制使用 USE_NL ?我如何知道 pl/sql 的哪个区域导致了这种情况,因为它被多次调用。

28/08 更新 - 添加了赏金。如果有任何额外要求,请告诉我。

2009 年 1 月更新 -

> SELECT XMLCONCAT (  XMLELEMENT (  "1",  (SELECT XMLCONCAT(  XMLELEMENT
> (  "2",  XMLELEMENT (  "3",  XMLFOREST (  )),  CASE  WHEN   THEN    
> XMLELEMENT (  "3",  XMLFOREST (  ))  END),  /*   (SELECT XMLELEMENT ( 
> "4",  XMLAGG (XMLELEMENT ("5")))  FROM TABLE t1,  t2  WHERE t1.col1 =
> t2.col2)  ,*/    CASE  WHEN   THEN  (SELECT XMLAGG (  XMLELEMENT ( 
> "5", */(SELECT col1  FROM TABLE t1,  t2  WHERE t1.col1 = t2.col2),*/ 
> XMLFOREST ( ....

有两个被注释掉的选择,当其中一个被取消注释时,它们会变成一个执行速度更快的查询。 t1 和 t2 根本不在查询中的其他地方使用。

更新 01/09 以下是执行计划: 快http://pastebin.com/pbJMSxrBhttp://pastebin.com/zt3eUYNd

这是我希望纠正的第 86 行中的高成本。这可能是此处完整扫描的结果,也可能是进一步向上连接的结果。

【问题讨论】:

  • 您可以发布您的表,其中包含任何索引以及您的查询吗?
  • 嗨,我打算发布 pl/sql 但是它很长(超过 1000 行)- 实际上格式是 xmlconcat ( xml agg ( xml agg (case ( xmlagg select value1,2 ,3 来自视图 1 2 3 其中 view1 value1 = view2 value2 和 view1 value1 = view3 value3 ) ..... 我引用的视图是同一张表 x3 只是分成不同的类,例如视图 = class1+class2+class3 的聚合. 抱歉,如果这仍然有点不清楚。
  • 您可以将其作为文件发布。我认为语法可能是一个问题。你能具体 'index(view_alias.table1_alias table1_index) index(view_alias.table2_alias table2_index)'
  • 这个提示应该出现在第一个选择中还是出现在“来自”之前的那个?或者它应该在 from 之后进行,例如FROM /*+ index(view,table1index) index(view,table2index) index(view,table3index) */ schema.view_to_use view ....
  • t1 和 t2 -- 它们是视图,是吗?如果是,视图定义是什么?

标签: sql oracle query-tuning optimizer-hints


【解决方案1】:

查询中的微小变化可能会对查询的不同部分产生影响。在这里,更改影响了视图 VIP_CODES_VW 的连接方式(它在两个地方完成,但第二个对性能的影响更大):在 fast 查询中,它是使用 NESTED LOOPS 完成的(第 79 行),在 slow 之一 - HASH JOIN(第 75 行)。要告诉优化器使用NESTED LOOPS,您可以在SELECT 之后添加提示/*+ USE_NL(VIP_CODES_VW) */,其中查询VIP_CODES_VW

【讨论】:

  • 嗨,之后在哪里?我已经用 (SELECT /*+ USE_NL(VIP_CODES_VW) 替换了所有 (SELECT /*+ USE_NL(VIP_CODES_VW) (只是为了确保我有所有实例)。 (SELECT /*+ USE_NL(VIP_CODES_VW) */XMLCONCAT ( CASE ..... ( SELECT /*+ USE_NL(VIP_CODES_VW) */MAX ( .... etc. 但性能是一样的。问题是函数中有多个嵌套语句和此视图的使用。
  • 您可以发布引用 VIP_CODES_VW 的子查询吗?如果有两个,他们两个。可以在pastebin.
  • 视图位于另一个模式 (tvic) 上,因此通常您还需要在提示中添加前缀,但您也可以使用别名 (vip),这样更简单。试试这个:pastebin.com/Hrsji1sM.
  • pastebin.com/Wg4vREcm 这是新函数的结果。不过,我觉得这是在正确的轨道上(根据我之前的更新)。
  • 计划有所改变,但最糟糕的HASH JOIN 仍然存在。该提示只是一个提示,即 Oracle 不需要服从它。尝试将/*+ FIRST_ROWS */ 提示添加到顶级查询(在慢查询中的第一个SELECT 之后)。此提示使 Oracle 更喜欢 NESTED LOOPS 而不是 HASH JOIN
【解决方案2】:

不使用索引的一个原因是理论上存在空值的可能性。空值没有索引,因此如果您的查询需要/认为可能存在空值,则无法通过索引访问表。

此外,您的提示必须与您的表的读取位置处于同一级别:

select /*+parallel(table_a)*/ ...
from (
      select ...
      from table_a
      ...
      )
...

不会工作

但是

select  ...
from (
      select /*+parallel(table_a)*/ ...
      from table_a
      ...
      )
...

会起作用的。

【讨论】:

  • 嗨,我已经尝试将提示几乎无处不在,但它不起作用。我遇到的问题是我有这个选择并且它运行缓慢,但是当我使用不同的表插入另一个选择时,它执行良好,没有缓冲区失败/哈希连接。查看更新了解更多详情
  • 您是否尝试在视图中插入提示?这就是我在回答中所说的:将提示放在引用表的位置。
  • 我将创建一个新视图 - 提示是否应该相同(平行)?
  • 不。使用您需要的提示:/*+ index(t1 t1_index_name) index(t2 t2_index_name) use_nl(t1 t2)
  • 我将此添加到视图中?我是否将它们全部放入每个选择中(请记住,此视图中有 3 个表) CREATE VIEW... SELECT /*+ index(tvic.vip_codes TVIC.VIP_CODES_IDX) index(tvic.vip_lcv_codes TVIC.VIP_LCV_CODES_IDX) use_nl (tvic.vip_codes tvic.vip_lcv_codes)*/ cols from table1... SELECT(T2 的另一个提示?)来自 T2.... SELECT(另一个提示 T3?)?
猜你喜欢
  • 2016-08-03
  • 1970-01-01
  • 2015-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-25
  • 2020-11-23
  • 1970-01-01
相关资源
最近更新 更多