排行
数据库百科
核心案例
行业报告
月度解读
大事记
产业图谱
中国数据库
向量数据库
时序数据库
实时数据库
搜索引擎
空间数据库
图数据库
数据仓库
大调查
2021年报告
2022年报告
年度数据库
2020年openGauss
2021年TiDB
2022年PolarDB
2023年OceanBase
首页
资讯
活动
大会
学习
课程中心
推荐优质内容、热门课程
学习路径
预设学习计划、达成学习目标
知识图谱
综合了解技术体系知识点
课程库
快速筛选、搜索相关课程
视频学习
专业视频分享技术知识
电子文档
快速搜索阅览技术文档
文档
问答
服务
智能助手小墨
关于数据库相关的问题,您都可以问我
数据库巡检平台
脚本采集百余项,在线智能分析总结
SQLRUN
在线数据库即时SQL运行平台
数据库实训平台
实操环境、开箱即用、一键连接
数据库管理服务
汇聚顶级数据库专家,具备多数据库运维能力
数据库百科
核心案例
行业报告
月度解读
大事记
产业图谱
我的订单
登录后可立即获得以下权益
免费培训课程
收藏优质文章
疑难问题解答
下载专业文档
签到免费抽奖
提升成长等级
立即登录
登录
注册
登录
注册
首页
资讯
活动
大会
课程
文档
排行
问答
我的订单
首页
专家团队
智能助手
在线工具
SQLRUN
在线数据库即时SQL运行平台
数据库在线实训平台
实操环境、开箱即用、一键连接
AWR分析
上传AWR报告,查看分析结果
SQL格式化
快速格式化绝大多数SQL语句
SQL审核
审核编写规范,提升执行效率
PLSQL解密
解密超4000字符的PL/SQL语句
OraC函数
查询Oracle C 函数的详细描述
智能助手小墨
关于数据库相关的问题,您都可以问我
精选案例
新闻资讯
云市场
登录后可立即获得以下权益
免费培训课程
收藏优质文章
疑难问题解答
下载专业文档
签到免费抽奖
提升成长等级
立即登录
登录
注册
登录
注册
首页
专家团队
智能助手
精选案例
新闻资讯
云市场
微信扫码
复制链接
新浪微博
分享数说
采集到收藏夹
分享到数说
首页
/
119-从is null能否走索引说起
119-从is null能否走索引说起
老虎刘谈oracle性能优化
2025-03-25
252
这是小技巧, 可能很多有经验的DBA已经知道了, 特别是参加过我
索引专题培训
的学员们. 今天再展开来讲讲.
有下面这样一个简单SQL, object_id字段上有索引, 请问是否会走索引:
select * from t1 where
object_id is null
;
思考一下.
......
回答这个问题, 有两个条件还要知道:
1. 使用的什么数据库 ;
2. 满足object_id is null 条件的记录数有多少.
老虎刘的回答是:
如果不是oracle数据库, 而且满足object_id is null的
记录数比较少
的时候,默认就是可以走索引的. 如果不走索引, 也可以通过hint强制使用. db2和sql server我没测过, mysql/postgresql/国产库, 都可以.
但如果是oracle数据库,即使满足object_id is null的记录数比较少, 也不会走索引,
使用hint强制也不行
. 因为oracle的BTree索引比较特殊, 不保存
全是null
的条目. object_id = null的记录就没有保存在索引中, 所以也就没办法走索引. 这是oracle数据库的索引跟其他数据库不同的地方,
很多从其他库转到oracle数据库的DBA和开发人员, 这个特性需要特别注意.
如何解决这个问题?
只需要来点小技巧, 那就是创建一个联合索引(
不需要改写SQL
):
create index idx_t1_object_id on t1(object_id,0)
;
如果object_id 是null ,但是后面的0 不是null, 这个记录就会保存在索引里面, 能走索引也就理所当然了. 这个时候如果再不走索引, 使用hint就一定没问题了. 原来object_id单字段索引可以删掉.
我还见过有人这样解决这个问题:
创建 nvl(object_id,-1) 函数索引, 也是可以的, 但是属于笨方法:
1.对应的SQL也要修改成:select * from t1 where
nvl(object_id,-1) = -1
;
2.原来object_id字段上的索引还需要保留, 要同时维护两个索引.
补充:
不要见到is null就想套用这种方法,下面这种SQL, 你永远也不要想它走索引:
select * from t1 a
left join t2 b
on a.object_id=b.object_id
where b.object_id is null
;
思考题:
select * from t1 where
object_id is null and object_type='TABLE'
;
需要两个字段才能过滤掉大部分记录的情况, 你会创建怎样的索引?
虽然是个小技巧, 还是有很多人不知道, 包括一下优化专家, 补充几个相关案例:
相关案例1:
这个是某银行的业务系统, t.transresult 字段上是有索引的, 但是仍使用了全表扫描, 导致存储负载超压,影响了使用共享存储的多套数据库, 出现严重的生产故障. 开发人员是通过删除历史数据,重建表解决的问题, 如果知道了上面的技巧, 不需要删除历史数据, 也能让SQL高效执行.
相关案例2:
这是优化专家给某银行做的优化建议,不需要与常量关联的时候,就没必要加个常量做联合了. 而且常量1需要占两个字节, 常量0只需要占一个字节. 生搬硬套也不可取.
相关案例3:
专家最后靠增加一个条件, 也实现了优化, 但是问题的根本原因还是没有给出. 其实也是BTree索引不保存null的原因.
很多时候, 在不知道基本原理的时候, 靠各种尝试, 也可能实现优化.
相关案例4:
SQL得到了优化, 但是改了SQL, 增加的那个0=0 不知道是为了什么. 说明还是没有真正理解背后的基本原理.
(全文完)
oracle索引
数据库
oracle
mysql创建索引
索引
文章转载自
老虎刘谈oracle性能优化
,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。
评论
领墨值
有奖问卷
意见反馈
客服小墨