Oracle 优化器不接受索引提示

Posted

技术标签:

【中文标题】Oracle 优化器不接受索引提示【英文标题】:Oracle optimizer is not accepting index hint 【发布时间】:2013-03-14 11:37:10 【问题描述】:

当我运行合并查询时,索引无法读取并且查询运行速度很慢,请告诉我。

stage_dim_accounts(rbc_code)中的索引

map_rbc_etl(free_code_9) 中的索引

MERGE INTO stage_dim_accounts t 
USING map_rbc_etl s ON (t.rbc_code = s.free_code_9)
WHEN MATCHED THEN UPDATE 
SET t.indx_no= s.indx_no  
WHERE s.annexure= 'AXN-I' 
AND (.free_code_9 <> 'NA' AND s.free_code_9   <> '0') 
AND t.rbc_code <> 'NA'

提前致谢

【问题讨论】:

explain plan 说什么? 请查看您的帖子。您在索引中列出的列与代码中的列不匹配(它们已切换)。 MAP_RBC_ETL.ANNEXUREMAP_RBC_ETL.FREE_CODE_9STAGE_DIM_ACCOUNTS.RBC_CODE 是否可以为空?如果是,哪些可以为空,哪些不能? 【参考方案1】:

优化器足够聪明,知道您的索引是无用的。

如果free_code 上的大多数值是“0”或“NA”,则该列中的索引可能很有用。由于您没有提供有关数据量或分布的任何信息,我们无法确定。但是您对map_rbc_etl 有其他限制条件,因此无论如何数据库都需要转到表中。我的猜测是优化器选择在 map_rbc_etl 上使用全表扫描,因为这比大量索引读取要快。

这是因为索引读取是两个操作 - 读取索引,读取行。因此,只有当读取的行的 百分比 很小时,它才会派发红利。否则,读取所有行并将它们筛选到内存中会更有效。

这是调优的“秘密”:索引读取并不总是更快;全表扫描并不总是坏事。

类似的逻辑适用于读取stage_dim_accounts。索引列不太可能是选择性的。除非...除非map_rbc_etl 中的行数非常少并且仅​​匹配stage_dim_accounts 中的一小部分行。我之前对数据指标的评论再次适用。

【讨论】:

【参考方案2】:

要使用的索引 在 map_rbc_etl(free_code_9,附件) 在 stage_dim_accounts(rbc_code) 上;

现在这些可能由于先前答案中的原因而无法使用。 可能不使用索引的其他原因是: 1. 优化器认为不使用索引会更有效。 2. 如果列在视图中并且在列上有函数调用。要使用此使用基于函数的索引。 3.你在查询中进行数学运算。请注意,您可以查看解释计划并创建索引以匹配其加载行的方式。 4. 在 where 子句中将列连接在一起。使用基于函数的索引来克服这一点。 5. 您没有在语句的 where 子句中包含连接索引中的第一列。请注意,Oracle 9i 或更高版本会跳过扫描并且可以使用索引。 6.你使用or子句。在这种情况下,最好为除 or 子句之外的所有子句创建一个索引,并为每个 or 值创建一个索引,然后它将适当地使用所有索引。

如果您不知道如何使用基于函数的索引,可以使用 where 子句中的 to_upper() 示例

create indexName on tableName(to_upper(colname));

任何 oracle sql 函数(内置的或用户创建的)都可以在索引中。

【讨论】:

以上是关于Oracle 优化器不接受索引提示的主要内容,如果未能解决你的问题,请参考以下文章

MySql 优化器不使用 varchar 上的索引

pennylane优化器不更新参数

Oracle索引HINT的使用

Oracle优化器模式不同导致索引失效

Oracle优化器模式不同导致索引失效

lightdb21.3-新增优化器提示no_merge