为什么 Oracle 不对非唯一索引使用索引全扫描?

Why Oracle Doesn't Use Index Full Scan on Non-Unique Indexes?

我在 HR 架构中创建了员工 table 的副本。然后在 employee_id 列上添加了一个非唯一索引。

create table employees1 as select * from employees;
create index temp_idx on employees1(employee_id);

然后查看其"select employee_id from employees;"的执行计划,进行了全table扫描,成本为3。但是,当我创建唯一索引时,它进行了索引全扫描,成本为1.

据我所知,oracle 创建唯一索引和非唯一索引的方式是相同的。因此两个索引中的叶数等应该相同。所以在这种情况下,虽然它可以 select 使用非唯一索引索引全扫描并将成本降低到 1,但为什么它选择全 table 扫描并导致更糟糕的计划?顺便说一句,我在创建 table 后没有删除或插入任何行。

你所说的在存在唯一索引的情况下执行计划是不正确的。 (我刚刚检查了我的机器 - 即使使用唯一索引,Oracle 仍然会执行完整扫描。)

这很有道理。无论索引是否唯一,当 EMPLOYEE_ID 为 NULL 时它不会存储任何内容。另一方面,如果有任何空行 EMPLOYEE_ID,它们应该由查询返回 - 所以查询不能单独查看索引。

如果您希望 Oracle 进行索引扫描,您必须告诉 Oracle 该列是 NOT NULL(当列是 primary key 时会自动发生 - 也许您对此感到困惑和 "unique index"),或者你必须 "select employee_id ... WHERE EMPLOYEE_ID IS NOT NULL"。您可能知道 "not null" 条件无论如何对所有行都为真,但 Oracle 直到从 table - 或 [=20= 读取所有数据后才会知道这一点] 如果在列上放置 not null 约束。如果您明确声明您只需要非空值,Oracle 就知道它可以使用索引。 (而且,索引是否唯一并不重要!)