在只有两种类型的值的列上创建索引有多有效

How effective is creating index on column having two types of values only

我在一列上创建了一个索引,它只有两个可能的值(Y 和 N),两个值的数据类型相同。

假设列名是指标。 我写了一个 select 语句,例如

SELECT INDICATOR 
FROM TEMP_TABLE 
ORDER BY INDICATOR

当我在 SQL 开发人员中为此查询使用解释计划时,它使用的是完整 table 扫描而不是索引扫描。

为什么不使用索引 table 扫描。

为了在 table 中找到没有索引的记录,DBMS 需要读取所有记录以找到匹配项。有了索引,DBMS 应该只需要读取一组连续的记录来找到匹配项,然后再去 table 中找到相应的记录。所以当 DBMS 使用索引时有一个额外的步骤。

作为一个粗略的经验法则,如果您从 table 读取超过 5% 的记录,那么完整 table 扫描将比索引查找更快。

但是数据的分布也很重要。考虑 99% 的数据是 'Y' 的情况。使用索引来解析具有 'Y' 的记录将非常低效(应用我的经验法则的反面,它比完整的 table 扫描花费的时间长 20 倍)。 OTOH 使用索引查找 'N' 的记录比完整的 table 扫描效率高 5 倍。

这就是 Oracle 对更复杂的索引属性使用直方图的原因。

Oracle 还具有称为绑定窥视的功能 - 它利用分布问题根据正在搜索的谓词选择最有效的查询。花点时间想想当查询模式与数据模式匹配时会发生什么——缓存的计划将取决于首先处理哪个版本的查询。

简短版本:不要在基数非常低的(一组)属性上使用索引。

索引 - 至少在 Oracle 中,我不知道其他数据库 - 不存储基础列的 NULL。由于您要求从列中读取所有值,因此 Oracle 需要从基础 table 中读取它们(即使您只读取索引列 - 一个明显的情况是无论基数估计如何都应该使用索引和其他因素)。

现在,也许您会说您的列中没有 NULL - 您说的是真的,每一行都有 'Y' 或 'N',没有 NULL。

没关系,但只有在检索数据并检查后才能知道。相反,如果您希望按预期使用索引,Oracle 需要知道在不先查看数据的情况下该列中不会有 NULL。这意味着:您需要 table 上的 CONSTRAINT。如果实际上该列应该为 NOT NULL,您可以

ALTER TABLE TEMP_TABLE MODIFY (INDICATOR NOT NULL);

或者,

SELECT INDICATOR 
FROM TEMP_TABLE
WHERE INDICATOR IS NOT NULL    --  ADDED! 
ORDER BY INDICATOR

将使用索引(试试吧!);但是如果该列不应该为 NULL,那么为什么不使用约束来明确这一点。