【问题标题】:Why Oracle Doesn't Use Index Full Scan on Non-Unique Indexes?为什么 Oracle 不对非唯一索引使用索引全扫描?
【发布时间】:2020-09-09 21:49:53
【问题描述】:

我在 HR 模式中创建了雇员表的副本。然后在employee_id 列上添加一个非唯一索引。

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

然后查看它的执行计划“selectemployee_id from employees;”,执行全表扫描,代价为3。然而,当我创建唯一索引时,执行索引全扫描,代价为1。

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

【问题讨论】:

  • 这取决于很多因素。表中有多少行?每行在磁盘上消耗多少存储空间(多少字节)?
  • @Bohemian - 它不应该依赖任何东西。 OP 正在选择 all 行,因此问题不在于使用索引进行快速访问。无论哪种方式都将执行完整扫描。 OP 的问题(有点误导,正如我在我的回答中解释的那样)是为什么 Oracle 不会从索引中读取所有 employee_id 值,在所有情况下它都应该小于整个表(整行)。跨度>

标签: oracle database-performance sqlperformance sql-tuning


【解决方案1】:

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

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

如果您希望 Oracle 进行索引扫描,您必须告诉 Oracle 该列是 NOT NULL(当该列是 primary key 时会自动发生 - 也许您对它和“唯一索引”感到困惑) ,或者您必须“选择employee_id ... WHERE EMPLOYEE_ID IS NOT NULL”。您可能知道无论如何“非空”条件对于所有行都是正确的,但 Oracle 直到它从表中读取所有数据之后才会知道这一点 - 如果您放置 not null列上的约束。如果您明确声明您只需要非空值,Oracle 知道它可以使用索引。 (同样,索引是否唯一并不重要!)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-27
    • 2020-12-04
    • 1970-01-01
    • 1970-01-01
    • 2013-10-01
    • 2014-12-18
    • 1970-01-01
    相关资源
    最近更新 更多