我们的文章会在微信公众号IT民工的龙马人生和博客网站( www.htz.pw )同步更新 ,欢迎关注收藏,也欢迎大家转载,但是请在文章开始地方标注文章出处,谢谢!
由于博客中有大量代码,通过页面浏览效果更佳。
本文为个人学习《Expert Oracle Database Architecture Techniques and Solutions for High Performance and Productivity(第四版本》一书过程中的笔记与理解分享,仅用于学习与交流,部分内容参考原书观点并结合>实际经验进行整理。若涉及版权问题,请联系删除或沟通处理。也请大家支持购买原版书籍。
什么时候该用B*树索引?一个接地气的解读
相信很多人在学数据库时都听过各种“经验法则”,比如“超过20%的数据就别用索引了”。但真实情况真是这样吗?其实并不尽然。今天我们就来聊聊B*树索引的使用时机,抛开死板的规则,用更实际的角度来理解。
两种看似矛盾,实则互补的情况
你可能听过两种完全相反的建议:
- 只有当查询会访问表中“很少一部分”数据时,才用B*树索引
- 当需要处理“大量”数据,但索引本身就能满足查询时,就用B*树索引
这俩听起来是不是互相打架?其实不然,它们分别对应了索引的两种完全不同用法。
用法一:用索引当“指针”去表里取数据
这种用法最常见。好比你先查书的目录(索引)找到章节页码,再翻到对应页(表)去读内容。
执行计划里你会看到:
INDEX RANGE SCAN -> TABLE ACCESS BY INDEX ROWID
关键点: 这个过程涉及两次操作——先读索引,再根据索引里的地址去表里找数据。每次根据索引找表数据,都可能产生一次磁盘读取(逻辑或物理I/O)。
什么时候好用?
当通过索引最终要访问的表数据量非常小的时候。这个“非常小”没有固定值:
- 对于“瘦”表(行少或列小),可能低于2%-3%
- 对于“胖”表(行多或列宽),这个比例可能高达20%-25%
为什么比例高了就不行?
想象一下,表就像一本1000页的书,分散放在地上。索引告诉你需要读第1、500、23、800、1、300、1……页。你不是顺序翻书,而是在满地书页中跳来跳去,还会反复翻看同一页(重复I/O)。如果要读的数据量很大,这种“东一榔头西一棒子”的方式效率极低,还不如从头到尾顺序读一遍(全表扫描)来得快。
用法二:用索引直接当“答案书”
这种用法更高级。索引本身已经包含了查询所需的全部信息,不需要再回表查数据。
执行计划里你会看到:
INDEX RANGE SCAN
(后面没有 TABLE ACCESS
)
关键点: 整个查询只在索引结构里完成,像是直接阅读一本提炼过的摘要书。这时,你访问索引中数据的比例可以是0%到100%,都可能是高效的,因为完全避免了耗时的表访问。
什么时候好用?
- 查询只涉及索引列时(如
SELECT index_column FROM table WHERE index_column = ?
) - 执行
COUNT(*)
等聚合查询,且条件都在索引上时 - 对响应速度要求高,用户希望立刻看到第一批结果(如分页查询)
一个生动的例子
假设一张表有10万行数据:
- 情况A:查询需要返回2万行数据,且必须回表取其他列。
- 表块大约1000个,索引访问需要2万次随机I/O,平均每个块被读20次。全表扫描更快(只需顺序读1000个块)。
- 情况B:查询需要返回2万行数据,但所有需要的列都在索引里。
- 数据库只读索引块,效率很高。用索引更快。
总结一下
该不该用B*树索引,不只看数据量比例,更要看查询如何访问数据:
- 索引当指针(回表查询):适合访问少量表数据,追求精确命中。
- 索引当答案(覆盖索引):适合任何比例的数据量,追求快速响应和避免表访问。
核心原则是:随机I/O(索引回表)的成本远高于顺序I/O(全表扫描)。如果你的查询会引发大量随机I/O,就需要谨慎评估。
所以,下次别再死记“20%”规则了。多看看执行计划,问问自己:我的查询到底是怎么取数据的?索引是充当“地图”还是“答案”?理解了这一点,你就能真正掌握索引使用的精髓。
------------------作者介绍-----------------------
姓名:黄廷忠
个人博客: (http://www.htz.pw)
CSDN地址: (https://blog.csdn.net/wwwhtzpw)
博客园地址: (https://www.cnblogs.com/www-htz-pw)