简体   繁体   English

Oracle加入表时选择了错误的索引

[英]Oracle picks wrong index when joining table

I have a long query, but similar to the short version here: 我有一个长查询,但类似于此处的短版本:

select * from table_a a

left join table_b b on

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

There are 2 indexes on table_b for both id and name , idx_id has fewer duplicates and idx_name has a lot of duplicates. 有2个索引table_b两个idnameidx_id具有较少的重复和idx_name有很多重复的。 This is quite a large table (20M+ records). 这是一个很大的表(超过20M条记录)。 And the join is taking 10min+. join需要10分钟以上。

A simple explain plan shows a lot of memory uses on the join part, and it shows it uses the index for name as opposed to id . 一个简单的解释计划显示了连接部分上大量的内存使用,并显示了它使用name索引而不是id

How to solve this issue? 如何解决这个问题? How to force using the idx_id index? 如何强制使用idx_id索引?

I was thinking of putting b.name='CONSTANT' to where clause, but this is a left join and where will remove all the record that exists in table_a. 我正在考虑将b.name='CONSTANT'放在where子句中,但这是一个左联接,where将删除table_a中存在的所有记录。


Updated explain plan. 更新了解释计划。 Sorry cannot paste the whole plan. 抱歉,无法粘贴整个计划。

Explain plan with b.name='CONSTANT' : b.name='CONSTANT'解释计划:

索引错误

Explain plan when commenting b.name clause: 在评论b.name子句时说明计划:

在此处输入图片说明

Add an optimizer hint to your query. 在查询中添加优化程序提示。

Without knowing your 'long' query, it's difficult to know if Oracle is using the wrong one, or if your interpretation that indexb < indexa so therefore must be quicker for query z is correct. 不知道您的“长”查询,很难知道Oracle使用的是错误的查询,还是很难理解您的解释indexb <indexa,因此对于查询z必须更快。

To add a hint the syntax is 要添加提示,语法是

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

What is the size of TABLE_A relative to TABLE_B? 相对于TABLE_B,TABLE_A的大小是多少? It wouldn't make sense to use the ID index unless TABLE_A had significantly less rows than TABLE_B. 除非TABLE_A的行数明显少于TABLE_B,否则使用ID索引是没有意义的。

Index range scans are generally only useful when they access a small percentage of the rows in a table. 索引范围扫描通常仅在访问表中一小部分行时才有用。 Oracle reads the index one-block-at-a-time, and then still has to pull the relevant row from the table. Oracle一次读取一个索引,然后仍然必须从表中提取相关行。 If the index isn't very selective, that process can be slower than a multi-block full table scan. 如果索引不是非常有选择性,那么该过程可能比多块全表扫描要慢。

Also, it might help if you can post the full explain plan using this text format: 另外,如果您可以使用以下文本格式发布完整的说明计划,则可能会有所帮助:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM