代码之家  ›  专栏  ›  技术社区  ›  Peter Recore

表中唯一字段的索引是否允许立即执行select count(*)。如果不是,为什么不呢?

  •  3
  • Peter Recore  · 技术社区  · 16 年前

    我对SQL调优的了解只够让自己陷入麻烦。今天我在一个查询上做了一个解释计划,我注意到在我认为应该使用索引时,它没有使用索引。嗯,在我解释之前,我一直在解释更简单(在我看来更容易索引)的问题。

    select count(*) from table_name
    

    我确信这会立即返回,解释会显示索引的使用,因为我们在这个表上有很多索引,包括行id列上的一个索引,它是唯一的。然而,“解释计划”显示了一个完整的表扫描,并且需要几秒钟才能完成。(此表中有300万行)。

    为什么Oracle要进行全表扫描来计算该表中的行数?我想认为,由于Oracle已经在索引唯一字段,并且必须跟踪该表上的每个插入和更新,所以它将在某个地方缓存行数。即使不是,扫描整个索引是否比扫描整个表更快?

    我有两种理论。理论一是我在想象指数是如何工作不正确的。理论二是,我们的Oracle设置中的某个设置或参数干扰了Oracle优化查询的能力(我们在Oracle9i上)。有人能启发我吗?

    3 回复  |  直到 16 年前
        1
  •  4
  •   Quassnoi    16 年前

    Oracle 不缓存 COUNT(*) .

    MySQL 具有 MyISAM 是的(能负担得起),因为 迈萨姆 无交易且相同 伯爵(*) 任何人都能看见。

    甲骨文公司 是事务性的,并且在其他事务中删除的行仍由事务可见。

    甲骨文公司 应该扫描它,看看它是否被删除,访问 UNDO ,确保从事务的角度来看,它仍然在适当的位置,并将其添加到计数中。

    索引A UNIQUE 值不同于索引非- 独特的 逻辑上只有一个。

    实际上,您可以创建一个 独特的 对定义了非唯一索引的列的约束,该索引将用于强制约束。

    如果列标记为非- NULL INDEX FAST FULL SCAN 在此列上可用于 COUNT .

    这是一种特殊的访问方法,用于索引顺序不重要的情况。它不会穿过 B-Tree 而是按顺序读取页面。

    由于索引的页数小于表本身,因此 伯爵 使用 INDEX_FFS 比用 FULL

        2
  •  2
  •   Dave Costa    16 年前

    Oracle当然可以使用索引(特别是使用索引快速完全扫描)来满足这样的查询。

    为了让优化器选择该路径,至少有两件事必须是正确的:

    1. Oracle必须确保表中的每一行都在索引中表示——基本上,索引中没有遗漏的空条目。如果你有一个主键,这应该是有保证的。
    2. Oracle必须将索引扫描的成本计算为低于表扫描的成本。我认为假设索引扫描总是更便宜并不一定是正确的。

    可能,在表上收集统计信息会改变行为。

        3
  •  0
  •   Brent Baisley    16 年前

    在“交易”原因上稍微扩展一点。当数据库支持事务时,在任何时间点上,可能会有不同状态的记录,甚至处于“已删除”状态。如果事务失败,状态将回滚。

    完成一个完整的表扫描,以便可以访问该时间点的每个记录的当前“版本”。

    mysql myisam没有这个问题,因为它使用表锁定,而不是事务所需的记录锁定,并缓存记录计数。所以它总是瞬间返回。mysql下的innodb与oracle工作相同,但返回和“estimate”。

    通过计算主键上的不同值,您可能能够更快地得到查询,然后只访问索引。