读书笔记:Oracle索引必知必会:避开这些坑,让你的数据库飞起来

我们的文章会在微信公众号IT民工的龙马人生博客网站( www.htz.pw )同步更新 ,欢迎关注收藏,也欢迎大家转载,但是请在文章开始地方标注文章出处,谢谢!
由于博客中有大量代码,通过页面浏览效果更佳。

本文为个人学习《Expert Oracle Database Architecture Techniques and Solutions for High Performance and Productivity(第四版本》一书过程中的笔记与理解分享,仅用于学习与交流,部分内容参考原书观点并结合>实际经验进行整理。若涉及版权问题,请联系删除或沟通处理。也请大家支持购买原版书籍。

Oracle索引必知必会:避开这些坑,让你的数据库飞起来

大家好!今天我们来聊聊Oracle索引那些最容易让人困惑的问题。很多开发者对索引存在误解,这些误解可能会导致性能问题甚至系统故障。让我来为大家一一解答这些常见问题。

视图能用索引吗?

简短回答:能!但不需要特意为视图创建索引

视图就像是一个保存好的查询语句。当你查询视图时,Oracle实际上是在执行视图背后的真实查询。所以关键在于:

  • 为基表(原始表)创建索引就够了
  • 视图会自动利用基表上的所有索引
  • 不需要也不能直接为视图创建索引

这就好比你要改善道路交通,不需要为导航软件修路,只需要把实际的道路修好就行。

NULL值和索引的爱恨情仇

这是最容易让人困惑的地方!B*Tree索引有个特点:完全不存储全部为NULL的记录

举个例子就明白了

假设我们有个员工表,在部门和职位上创建了唯一索引:

-- 插入各种组合的数据
INSERT INTO 员工表 VALUES (1, 1);        -- 存入索引
INSERT INTO 员工表 VALUES (1, NULL);     -- 存入索引(因为有1不是NULL)
INSERT INTO 员工表 VALUES (NULL, 1);     -- 存入索引(因为有1不是NULL)
INSERT INTO 员工表 VALUES (NULL, NULL);  -- 不存入索引!

神奇的事情发生了:最后一条全部为NULL的记录根本不会进入索引!

这就导致了两个重要现象:

  1. 查询WHERE x IS NULL可能用不上索引
    因为索引里根本没有全部为NULL的记录,如果用索引会漏掉数据

  2. 唯一索引可能不唯一
    你可以插入多条全部为NULL的记录,因为索引里根本没有这些记录

实战建议:如何让IS NULL查询使用索引

-- 确保至少有一列是NOT NULL
CREATE TABLE 员工表 (
    部门 INT,
    职位 INT NOT NULL  -- 这列不能为空
);

-- 创建索引
CREATE UNIQUE INDEX 索引名 ON 员工表(部门, 职位);

-- 现在查询IS NULL就能用索引了
SELECT * FROM 员工表 WHERE 部门 IS NULL;

高级技巧:利用NULL值优化索引

如果你的数据严重倾斜(比如90%是一种值,10%是另一种值),可以这样做:

  • 对多数值使用NULL
  • 对少数值使用实际值
  • 然后创建索引,这样索引只会包含少数值的记录,大大节省空间

外键必须建索引!这是血的教训

这是我见过最多死锁问题的根源!外键一定要建索引,原因如下:

1. 避免可怕的表锁

如果没有外键索引,当你更新或删除父表记录时,Oracle会在整个子表上加锁!这会导致:

  • 并发性能急剧下降
  • 容易产生死锁
  • 其他会话无法修改子表

2. 级联删除需要索引

如果设置了ON DELETE CASCADE,删除父表记录时会自动删除子表记录。没有索引的话,每次删除都要全表扫描子表,性能极差。

3. 关联查询需要索引

当你连接父表和子表进行查询时,外键索引能极大提升性能:

-- 没有外键索引,这个查询会很慢
SELECT *
FROM 部门表, 员工表
WHERE 员工表.部门编号 = 部门表.部门编号
AND 部门表.名称 = '销售部';

什么情况下可以不建外键索引?

只有同时满足以下三个条件时:

  1. 绝对不从父表删除数据
  2. 绝对不更新父表的主键
  3. 绝对不通过外键进行关联查询

但说实话,在实际项目中几乎不可能同时满足这三个条件。所以安全起见,永远为外键创建索引

诊断技巧:如何发现外键锁问题

如果你怀疑有外键锁问题,可以用这个命令来验证:

ALTER TABLE 子表名 DISABLE TABLE LOCK;

这样任何会导致锁表的操作都会立即报错,帮你快速定位问题。

总结

  1. 视图索引:不需要特意创建,用基表索引就行
  2. NULL值索引:理解B*Tree不存全NULL的特性,善加利用
  3. 外键索引:必须建!否则会引发死锁和性能问题

记住这些要点,你的Oracle数据库就能跑得更稳更快。索引是个强大的工具,用对了事半功倍,用错了后患无穷。希望这些实战经验对你有帮助!

------------------作者介绍-----------------------
姓名:黄廷忠
现就职:Oracle中国高级服务团队
曾就职:OceanBase、云和恩墨、东方龙马等
电话、微信、QQ:18081072613
个人博客: (http://www.htz.pw)
CSDN地址: (https://blog.csdn.net/wwwhtzpw)
博客园地址: (https://www.cnblogs.com/www-htz-pw)

posted @ 2025-09-23 14:58  认真就输  阅读(14)  评论(0)    收藏  举报