我们的文章会在微信公众号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的记录根本不会进入索引!
这就导致了两个重要现象:
-
查询
WHERE x IS NULL
可能用不上索引
因为索引里根本没有全部为NULL的记录,如果用索引会漏掉数据 -
唯一索引可能不唯一
你可以插入多条全部为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 部门表.名称 = '销售部';
什么情况下可以不建外键索引?
只有同时满足以下三个条件时:
- 绝对不从父表删除数据
- 绝对不更新父表的主键
- 绝对不通过外键进行关联查询
但说实话,在实际项目中几乎不可能同时满足这三个条件。所以安全起见,永远为外键创建索引。
诊断技巧:如何发现外键锁问题
如果你怀疑有外键锁问题,可以用这个命令来验证:
ALTER TABLE 子表名 DISABLE TABLE LOCK;
这样任何会导致锁表的操作都会立即报错,帮你快速定位问题。
总结
- 视图索引:不需要特意创建,用基表索引就行
- NULL值索引:理解B*Tree不存全NULL的特性,善加利用
- 外键索引:必须建!否则会引发死锁和性能问题
记住这些要点,你的Oracle数据库就能跑得更稳更快。索引是个强大的工具,用对了事半功倍,用错了后患无穷。希望这些实战经验对你有帮助!
------------------作者介绍-----------------------
姓名:黄廷忠
现就职:Oracle中国高级服务团队
曾就职:OceanBase、云和恩墨、东方龙马等
电话、微信、QQ:18081072613
个人博客: (http://www.htz.pw)
CSDN地址: (https://blog.csdn.net/wwwhtzpw)
博客园地址: (https://www.cnblogs.com/www-htz-pw)