让Oracle SQL优化器相信索引(尽管不是唯一的)列实际上包含唯一的值

让Oracle SQL优化器相信索引(尽管不是唯一的)列实际上包含唯一的值,sql,oracle,optimizer-hints,cost-based-optimizer,Sql,Oracle,Optimizer Hints,Cost Based Optimizer,我正在编写一个视图,它使用一个列,列上有一个非唯一的索引。然而,在我的观点中,我相信该列将只包含唯一的值(由于WHERE子句中施加的条件) 真正的问题发生在有人基于该列查询视图时(例如,从MY_视图中选择*,其中列具有非唯一索引='foo')。优化器确信它将接收许多行(因为索引在技术上不是唯一的)。正因为如此,优化器避免在视图中的其他位置使用其他索引,而支持全表扫描(不酷) 有没有一种方法可以让优化器相信,具有非唯一索引的列实际上将包含唯一的值?当然,重复值有可能潜入列中,但这将被视为一个bug

我正在编写一个视图,它使用一个列,列上有一个非唯一的索引。然而,在我的观点中,我相信该列将只包含唯一的值(由于
WHERE
子句中施加的条件)

真正的问题发生在有人基于该列查询视图时(例如,
从MY_视图中选择*,其中列具有非唯一索引='foo'
)。优化器确信它将接收许多行(因为索引在技术上不是唯一的)。正因为如此,优化器避免在视图中的其他位置使用其他索引,而支持全表扫描(不酷)

有没有一种方法可以让优化器相信,具有非唯一索引的列实际上将包含唯一的值?当然,重复值有可能潜入列中,但这将被视为一个bug,不应导致合法、唯一的数据受损


不幸的是,我无法控制所讨论的表(叹气)。

您可以尝试以下方法:

使用dbms_stats和METHOD_OPT将表上的统计信息收集为“所有列大小自动”使用此设置,Oracle将自动确定哪些列需要直方图以及每个直方图的存储桶数(大小)。您还可以手动指定哪些列应具有直方图以及每个直方图的大小

dbms_stats.gather_table_stats(
ownname => 'schemaname' ,
tabname => 'tablename' ,
estimate_percent => 100 ,
method_opt => 'for all indexed columns size auto' ,
 cascade => true);

Oracle允许您在视图上创建唯一(和主键)约束,这些约束未强制执行,但为优化器提供的正是此类信息

ALTER VIEW your_view_name
  ADD CONSTRAINT name_of_constraint UNIQUE( column_with_non_unique_index )
  RELY DISABLE NOVALIDATE;

这将告诉Oracle,它可以依赖这样一个事实,即数据是唯一的,但不需要验证约束。但是,优化器将能够使用约束提供的附加元数据。

您的统计数据是否最新?它应该已经使用了适当的索引,如果它们是,这确实是有利的。唯一索引/唯一约束告诉优化者你想告诉它什么。为什么你会认为还有其他方法可以做到这一点?@Mat:统计数据已经过时了,所以我在桌子上收集了统计数据。它改进了解释计划的某些部分,但没有改进这个特定部分。我会继续调查。@Dems:在看到优化器可用的所有提示后,我怀疑可能有什么东西可以提示此信息。如果要强制执行此操作,请尝试使用普通的/*+索引(…)*/hint并测量实际查询时间(而不仅仅是解释计划)。