找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

3054

积分

0

好友

406

主题
发表于 4 小时前 | 查看: 4| 回复: 0

在日常的 数据库 性能调优工作中,理解索引何时生效是开发者和DBA的基本功。我们一起来看看这个经典的场景:

假设在 Oracle 数据库中,我们通过以下语句创建了一个测试表 T,并为其 object_id 字段创建了索引。注意,T 表的 object_id 字段允许为 NULL

create table t as select * from dba_objects;
create index idx_t_object_id on t(object_id);

现在的问题是,针对这个表结构,以下哪些 SQL 语句会利用到我们创建的 idx_t_object_id 索引来返回记录?

选项如下:

A、select count(*) from t;

B、select count(object_id) from t where object_id is not null;

C、select avg(object_id) from t ;

D、select avg(object_id) from t where object_id is not null;

E、select count(object_id) from t;

F、select count(*) from t where object_id is not null;

核心知识点解析

要正确回答这个问题,需要理解 Oracle 索引的这几个关键行为:

  1. 索引与 NULL 值:在 B-Tree 索引中,所有键值(KEY)为 NULL 的记录通常不会被存储。因此,如果一个列允许为 NULL,那么仅基于该列的索引无法覆盖表中的所有行。
  2. 聚合函数的行为:像 COUNT(column) 这样的聚合函数,会自动忽略该列的 NULL 值,只统计非 NULL 的行。而 COUNT(*) 则是统计表中的所有行,不论字段值是否为 NULL
  3. 优化器的选择:当查询可以通过扫描一个更小、更紧凑的索引来获得结果,而无需访问表时,优化器通常会选择“索引快速全扫描(INDEX FAST FULL SCAN)”或“索引全扫描(INDEX FULL SCAN)”,这比全表扫描要高效得多。

逐项分析

基于以上原则,我们来分析每个选项:

  • *A、`select count() from t;** 此查询需要统计**表中所有行的数量**。由于object_id索引不包含NULL值,因此它无法提供完整的行数信息(如果表中有object_idNULL的行)。为了得到准确结果,优化器必须进行全表扫描(FULL TABLE SCAN),而不会使用idx_t_object_id` 索引。

  • B、select count(object_id) from t where object_id is not null;
    这个查询的意图很明确:统计 object_id 非空的行数。由于 WHERE 子句过滤掉了 NULL 值,结果集完全落在了索引覆盖的范围内。优化器可以仅通过扫描 idx_t_object_id 索引(索引快速全扫描)就得到结果,无需回表。因此,这条语句会利用索引

  • C、select avg(object_id) from t;
    计算整个表 object_id 列的平均值。AVG(column) 函数同样会忽略该列的 NULL 值。虽然索引包含了所有非 NULLobject_id 值,但要计算平均值,还需要知道参与计算的行数。如果表中有 object_idNULL 的行,仅扫描索引无法得知这些行的存在(它们不在索引中),从而可能影响对总行数的判断(用于计算平均值)。因此,优化器通常不会冒险使用索引,而是选择全表扫描。

  • D、select avg(object_id) from t where object_id is not null;
    与选项B同理,WHERE object_id is not null 确保了数据处理范围完全被索引覆盖。要计算平均值,需要非 NULL 值的总和以及它们的个数,这些信息都可以通过扫描 idx_t_object_id 索引直接获得(因为索引键值就是 object_id 本身)。所以,这条语句也会利用索引

  • E、select count(object_id) from t;
    如前所述,COUNT(column) 只统计该列非 NULL 的行。这正好与索引所包含的数据范围(所有非 NULLobject_id完全一致。因此,优化器可以高效地使用索引快速全扫描来获得精确计数,这是典型的索引适用场景

  • F、select count(*) from t where object_id is not null;*
    这个查询容易被误解。WHERE object_id is not null 限定了范围,但 `COUNT(
    )` 仍然是要统计
    满足条件的行数。所有满足 object_id is not null 条件的行,其 object_id 值都必然存在于 idx_t_object_id 索引中。优化器可以通过扫描索引来计数,而无需访问表。因此,这条语句同样会利用索引**。

总结

综上所述,能有效利用到 idx_t_object_id 索引的SQL语句是:B、D、E、F

理解索引、NULL 值以及聚合函数之间的微妙关系,对于编写高效的 SQL语句 至关重要。希望这个分析能帮助你更深入地掌握 Oracle 索引的使用场景。如果你在实践中有其他有趣的发现,欢迎到 云栈社区 分享和讨论。




上一篇:STM32H5工业互联设备管理系统从入门到精通 基于Modbus与FreeRTOS的嵌入式全栈项目实战
下一篇:研究揭示:PropensityBench基准测试下,压力如何驱动AI智能体突破安全规则
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-4-15 04:27 , Processed in 0.684210 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表