【问题标题】:Oracle picks wrong index when joining tableOracle 在加入表时选择了错误的索引
【发布时间】:2015-08-03 08:43:17
【问题描述】:

我有一个很长的查询,但类似于这里的简短版本:

select * from table_a a

left join table_b b on

b.id = a.id and
b.name = 'CONSTANT';

idnametable_b 上有 2 个索引,idx_id 的重复项较少,idx_name 的重复项很多。这是一个相当大的表(20M+ 记录)。 join 需要 10 分钟以上。

一个简单的解释计划显示连接部分使用了大量内存,它显示它使用name 的索引而不是id

如何解决这个问题?如何强制使用idx_id 索引?

我正在考虑将b.name='CONSTANT' 放在 where 子句中,但这是一个左连接,where 将删除 table_a 中存在的所有记录。


更新了解释计划。抱歉无法粘贴整个计划。

b.name='CONSTANT'解释计划:

评论b.name子句时说明计划:

【问题讨论】:

  • 一个简单的解释计划显示了连接部分的大量内存使用,它表明它使用索引作为名称而不是 id。 那么,解释在哪里计划?
  • 两个表的统计信息都是最新的吗?
  • 没有完整的计划,这是浪费时间。

标签: sql oracle indexing query-performance


【解决方案1】:

为您的查询添加优化器提示。

在不知道您的“长”查询的情况下,很难知道 Oracle 是否使用了错误的查询,或者您对 indexb

要添加提示,语法是

select /*+ index(table_name index_name) */ * from ....;

【讨论】:

    【解决方案2】:

    TABLE_A 相对于 TABLE_B 的大小是多少?除非 TABLE_A 的行数明显少于 TABLE_B,否则使用 ID 索引是没有意义的。

    索引范围扫描通常仅在访问表中一小部分行时才有用。 Oracle 一次一个块地读取索引,然后仍然必须从表中提取相关行。如果索引不是很有选择性,那么该过程可能比多块全表扫描要慢。

    此外,如果您可以使用此文本格式发布完整的解释计划,这可能会有所帮助:

    explain plan for select ... ;
    select * from table(dbms_xplan.display);
    

    【讨论】:

      猜你喜欢
      • 2012-01-02
      • 1970-01-01
      • 1970-01-01
      • 2011-10-18
      • 2019-12-19
      • 2017-10-24
      • 2014-04-18
      • 2016-05-03
      • 1970-01-01
      相关资源
      最近更新 更多