仅在具有两种类型的值的列上创建索引的效果如何

vdicta 发布于 2019-11-08 oracle 最后更新 2019-11-08 22:59 11 浏览

我在一列上创建了一个索引,它只有两个可能的值(Y和N),两个值的数据类型相同。 假设列名是指标。 我写了一个select语句,

SELECT INDICATOR 
FROM TEMP_TABLE 
ORDER BY INDICATOR
当我在SQL开发人员中对此查询使用解释计划时,它使用全表扫描而不是索引扫描。 为什么它不使用索引表扫描。
已邀请:

dsed

赞同来自:

索引 - 至少在Oracle中,我不知道其他数据库 - 不会从底层列存储NULL。由于您要求读取列中的所有值,因此Oracle需要从基表中读取它们(即使您只读取索引列 - 无论基数估计和其他因素如何都应该使用索引时的一个例子) 。 现在,也许你会说你的列中没有NULL - 你的意思是你所说的,每一行都有'Y'或'N',没有NULL。 没关系,但只有在检索数据并检查数据后才能知道。相反,如果您希望按预期使用索引,Oracle需要知道该列中没有NULL而没有先查看数据。这意味着:您需要桌面上的CONSTRAINT。如果实际上该列应该是非NULL,那么你可以

ALTER TABLE TEMP_TABLE MODIFY (INDICATOR NOT NULL);
或者,
SELECT INDICATOR 
FROM TEMP_TABLE
WHERE INDICATOR IS NOT NULL    --  ADDED! 
ORDER BY INDICATOR
将使用索引(试试吧!);但是如果列应该是NOT NULL,那么为什么不用约束来显式。

et_et

赞同来自:

为了在没有索引的表中查找记录,DBMS需要读取所有记录以找到匹配项。使用索引,DBMS应该只需要读取一组连续的记录来查找匹配,然后在表中找到相应的记录。因此,当DBMS使用索引时,还有一个额外的步骤。 作为一个粗略的经验法则,如果您从表中读取超过5%的记录,那么全表扫描将比索引查找更快。 但数据的分布也很重要。考虑99%的数据为“Y”的情况。使用索引来解析带有'Y'的记录将非常有效(应用我的经验法则的倒数,它将比全表扫描长20倍)。 OTOH使用索引查找带有'N'的记录将比全表扫描效率高5倍。 这就是Oracle将直方图用于更复杂的索引属性的原因。 Oracle还有一个名为bind peeking的功能 - 它利用分发问题根据搜索的谓词选择最有效的查询。花点时间考虑当查询模式与数据模式匹配时会发生什么 - 缓存计划将取决于首先处理查询的哪个版本。 简短版本:不要在基数非常低的(一组)属性上使用索引。