SQL优化 第一章 数据存储及索引

参考资料:
本系列博客主要参考资料有CUUG冉乃纲老师数据库教学笔记,《SQL优化核心思想》(罗炳森,黄超,钟侥著),《PostgreSQL技术内幕:查询优化深度探索》(张树杰著),排名不分先后。

1 事先说明

我们做SQL优化,其中最直截了当的利器便是索引,当然,也是一把双刃剑,既然讲到索引,我们就要讲表里的数据怎么存储的,只有这样,我们才会把索引的基本原理,为什么要建索引,怎么用索引理解清楚,也为后面的表连接做好基础。

2 数据存储

Oracle数据存储有着一整套完善的物理存储结构和逻辑存储结构,这里我们不多说,大家如果有需求,我们另开专题讲解。我们这里主要抓住三点。

(1)数据的存储是无序的,原因很简单,顺序存储耗时耗资源,也不利于存储结构优化,比如,热块(不理解就过了吧,我们临时理解为,这个是DBA要管的,DBA莫怪。。。);

(2)数据从磁盘到内存是按块读取的,不是按条读取的,原因很简单,块大小固定,读取快捷,当然,有时候是单块读,有时候多块一起读,我们会结合索引后面分析;

(3)数据库每一条记录对应唯一一个不变的虚拟列,叫rowid,这是定位数据最快的方式,因为rowid=数据对象编号+对应文件编号+块编号+行编号,好吧,又开始装了,我们理解为rowid是记录的物理地址。

综上三点,假设我们有一张表,怎么从里面找我们想要的数据呢,只能把表从头看到尾,把想要的拿出来,好吧这就是全表扫描。

那么问题来了,假设这张表很大,每天执行很多次查询,每次都全表扫,不说别的,IO成本就足以让系统奔溃掉。解决方案就是下面要说的,索引。

3 索引

3.1 用简单平衡树+双向链表解释索引

我们这里只说B树索引,关于位图索引,大家可以自己网上查询。

第一个问题,索引是啥?简要回答,索引的结构是树形结构+双向链表。有听不懂的小伙伴没关系,我们一层层剥开来讲。

假设我们把数据这么存储,也是平衡树+双向链表,关于数据查找,我们有如下分析

(1)假设我们要找数字7的时候,看根节点5->7大于5->右分支8->7小于8->左分支7,我们定位数据只用了三次,其实这就是索引唯一扫描;

(2)假设我们要找7和9之间的数据,通过上面定位7的方式找到7 ,然后在下面的双向链表往右扫描到10,发现已经大于9,停止扫描,其实这就是索引范围扫描

(3)索引跳跃扫描(skip scan)通过这个结构不好讲解,我们后面根据索引应用案例讲解。

关于平衡树和双向链表的构建,关键字是排序+折半查找,

(1)首先,把数字按照一定顺序排好,我们这里按照升序

(2)折半查找,找个偏中间值做根节点,这里是5,然后左右每个段再找个偏中间值做第一层分支,这里是2和8,一次类推,直到找完。

那么问题来了,索引是有序的吗?

答案是肯定的,第一步就是排序嘛!

那么索引的好处和坏处都来了,

(1)好处,快速定位,大家可以结合任何一张报纸不能被连续折叠20次来理解;

(2)坏处呢,也是显而易见,排序,每一次数据的更改,都要维护索引结构以及顺序,这就不难理解索引为什么影响增删改操作了;

(3)索引有时候也会对Select操作产生不好影响,这里讲为时过早,我们第三章 <3 全表扫描和索引扫描选择>再做讲解。

3.2 索引存储结构

上面我们只是用平衡二叉树简单理解索引,事实上,索引不是二叉树,如果是二叉树,索引会很高,也就是层次很多,一层层定位,会影响定位速度;

还有就是每个节点的数据结构是键值对,键是建立索引时的字段值,值是rowid,以实现表数据快速定位。

这就是索引结构图。

3.3 小结

(1)关于数据存储结构,我们理解无序+按块读+rowid概念就好了;

(2)关于索引结构,我们理解索引是树形结构+双向链表,节点里存字段值和rowid就好了,我们是做SQL优化,不是专门研究索引数据结构,理解就好,没必要深究。

猜你喜欢

转载自blog.csdn.net/songjian1104/article/details/91349914