写在前面:接上一节,本节主要讨论索引页面格式,以及索引与查询优化的关系。

(1)索引页面格式
sqlite> select * from sqlite_master;
table|episodes|episodes|2|CREATE TABLE episodes( id integer primary key,name tex
t, cid int)
index|name_index|episodes|3|CREATE INDEX name_index on episodes(name)
第3个页面保存表 episodes的索引(也只占一个页面)。

前8个字节为页面头:
0x0A:leaf+zerodata,表示叶子页面,且页面中只有关键字,没有数据(即索引页面);
0x0000:表示第一个空闲块的偏移为0;
0x0011:页面的单元数(记录数),该页面含有17个记录;
0x030D:单元内容区的第一个字节的偏移(距页面起始位置)
0x00:  碎片字节数
接下来34个字节为17个单元(记录)的指针数组。第一个单元的偏移为0x03EC,如

来看看索引单元的格式:
0x13:数据的字节数,19个字节,从0x03开始。
0x03:记录头的字节数。
0x2B:第一个字段的长度,15个字节,该索引是对episodes表的name字段建的,其值为episodes表name字段的值。
0x01:第二个字段的长度,其值为0x01,即episodes表中的对应记录rowid的值。

(2)索引与order by
order by是查询中经常用到的,一些通用DBMS(比如DM,Mysql)都提供基于索引的形式来实现Order by。SQLite也是通过索引来实现Order by的。当字段有索引时,则直接通过索引很容易实现排序;另一方面,如果排序的字段没有索引,则以该字段为索引(这种情况下是聚集索引)建立一张临时表,再将临时表按顺序输出。来看看sqlite的实现吧。

在sqlite中,默认以rowid来建立聚集索引(对于没有整型值主键的情况)。如果主键字段为整型,则将其直接保存在rowid中,实现聚集索引;另一方面,如果主键是字符串,则对主键建立二级索引。非主键的索引都属于二级索引。
先来看看以整型ID为主键的情况:


///////////////以ID(rowid)为索引(即聚集索引)
sqlite> explain select * from episodes order by id;
0|Trace|0|0|0|explain select * from episodes order by id;|00|
1|Noop|0|0|0||00|
2|Goto|0|13|0||00|
3|SetNumColumns|0|3|0||00|
4|OpenRead|0|2|0||00|        ;打开表episodes,p2(=2)为其根页面
5|Rewind|0|11|0||00|         ;游标指向第一条记录
6|Rowid|0|1|0||00|           ;取出记录的rowid
7|Column|0|1|2||00|          ;取出第1列的值
8|Column|0|2|3||00|          ;取出第2列的值
9|ResultRow|1|3|0||00|       ;生成记录结果
10|Next|0|6|0||01|           ;取下一条记录
11|Close|0|0|0||00|
12|Halt|0|0|0||00|
13|Transaction|0|0|0||00|
14|VerifyCookie|0|2|0||00|
15|TableLock|0|2|0|episodes|00|
16|Goto|0|3|0||00|

属性有索引的情况:


/////////////排序的实现——有索引
//算法思想:
//(1)从索引中依次读取记录(索引记录的形式如:原索引属性-rowid的键值),并取出rowid.
//(2)根据(1)中取出的rowid,在原表中查找记录,并生成记录结果.
sqlite> explain select * from episodes order by name;
0|Trace|0|0|0|explain select * from episodes order by name;|00|
1|Noop|0|0|0||00|
2|Goto|0|18|0||00|
3|SetNumColumns|0|3|0||00|
4|OpenRead|0|2|0||00|                  ;打开表,p1为表游标(0),p2为表根页面
5|SetNumColumns|0|2|0||00|
6|OpenRead|2|3|0|keyinfo(1,BINARY)|00| ;打开索引,p1为索引游标,p2为根页面
7|Rewind|2|15|1|0|00|
8|IdxRowid|2|1|0||00|                  ;从索引记录中取出rowid
9|Seek|0|1|0||00|                      ;根据rowid从表中查找记录
10|IdxRowid|2|2|0||00|
11|Column|2|0|3||00|
12|Column|0|2|4||00|
13|ResultRow|2|3|0||00|
14|Next|2|8|0||00|
15|Close|0|0|0||00|
16|Close|2|0|0||00|
17|Halt|0|0|0||00|
18|Transaction|0|0|0||00|
19|VerifyCookie|0|2|0||00|
20|TableLock|0|2|0|episodes|00|
21|Goto|0|3|0||00|

对于没有索引的属性排序:


////////////////排序的实现——没有索引
//(1)按查询属性为聚集索引建立一个临时表;
//(2)按索引顺序输出结果。
sqlite> explain select * from episodes order by cid;
0|Trace|0|0|0|explain select * from episodes order by cid;|00|
1|OpenEphemeral|1|3|0|keyinfo(1,BINARY)|00| ;p1为临时表游标,p2为临时表列数
2|Goto|0|30|0||00|
3|SetNumColumns|0|3|0||00|
4|OpenRead|0|2|0||00|       ;打开表episodes
5|Rewind|0|16|0||00|        ;游标移到表的第1条记录,p1为游标下标
6|Rowid|0|1|0||00|              ;p1为表的下标,p2指向表的记录
7|Column|0|1|2||00|         ;读取表p1(=0)的第1列
8|Column|0|2|3||00|         ;读取表p1(=0)的第2列
9|MakeRecord|1|3|4||00|
10|SCopy|3|5|0||00|
11|Sequence|1|6|0||00|
12|Move|4|7|1||00|
13|MakeRecord|5|3|8||00|
14|IdxInsert|1|8|0||00|     ;该指令在索引中插入记录,相当于对表的Insert. p1为索引下标,即OpenEphemeral打开的临时表
15|Next|0|6|0||01|
16|Close|0|0|0||00|         ;关闭表episodes
17|SetNumColumns|0|3|0||00|
18|OpenPseudo|2|1|0||00|    ;打开临时表
19|Sort|1|28|0||00|         ;与Rewind功能类似
20|Column|1|2|4||00|
21|Integer|1|8|0||00|
22|Insert|2|4|8||00|
23|Column|2|0|1||00|
24|Column|2|1|2||00|
25|Column|2|2|3||00|
26|ResultRow|1|3|0||00|     ;输出临时记录
27|Next|1|20|0||00|
28|Close|2|0|0||00|         ;
29|Halt|0|0|0||00|
30|Transaction|0|0|0||00|
31|VerifyCookie|0|2|0||00|
32|TableLock|0|2|0|episodes|00|
33|Goto|0|3|0||00|

 

SQLite入门与分析(八)---存储模型(3)的更多相关文章

  1. SQLite入门与分析(八)---存储模型(1)

    写在前面:SQLite作为嵌入式数据库,通常针对的应用的数据量相对于通常DBMS的数据量是较小的.所以它的存储模型设计得非常简单,总的来说,SQLite把一个数据文件分成若干大小相等的页面,然后以B树 ...

  2. SQLite入门与分析(八)---存储模型(2)

    3.页面结构(page structure) 数据库文件分成固定大小的页面.SQLite通过B+tree模型来管理所有的页面.页面(page)分三种类型:要么是tree page,或者是overflo ...

  3. SQLite入门与分析(二)---设计与概念(续)

    SQLite入门与分析(二)---设计与概念(续)   写在前面:本节讨论事务,事务是DBMS最核心的技术之一.在计算机科学史上,有三位科学家因在数据库领域的成就而获ACM图灵奖,而其中之一Jim G ...

  4. SQLite入门与分析(二)---设计与概念

    写在前面:谢谢各位的关注,没想到会有这么多人关注.高兴的同时,也感到压力,因为我接触SQLite也就几天,也没在实际开发中用过,只是最近项目的需求才来研究它,所以我很担心自己的文章是否会有错误,误导别 ...

  5. SQLite入门与分析(四)---Page Cache之事务处理(1)

    写在前面:从本章开始,将对SQLite的每个模块进行讨论.讨论的顺序按照我阅读SQLite的顺序来进行,由于项目的需要,以及时间关系,不能给出一个完整的计划,但是我会先讨论我认为比较重要的内容.本节讨 ...

  6. SQLite入门与分析(三)---内核概述(2)

    写在前面:本节是前一节内容的后续部分,这两节都是从全局的角度SQLite内核各个模块的设计和功能.只有从全局上把握SQLite,才会更容易的理解SQLite的实现.SQLite采用了层次化,模块化的设 ...

  7. SQLite入门与分析(四)---Page Cache之事务处理(2)

    写在前面:个人认为pager层是SQLite实现最为核心的模块,它具有四大功能:I/O,页面缓存,并发控制和日志恢复.而这些功能不仅是上层Btree的基础,而且对系统的性能和健壮性有关至关重要的影响. ...

  8. SQLite入门与分析(三)---内核概述(1)

    写在前面:从本章开始,我们开始进入SQLite的内核.为了能更好的理解SQLite,我先从总的结构上讨论一下内核,从全局把握SQLite很重要.SQLite的内核实现不是很难,但是也不是很简单.总的来 ...

  9. SQLite入门与分析(七)---浅谈SQLite的虚拟机

    写在前面:虚拟机技术在现在是一个非常热的技术,它的历史也很悠久.最早的虚拟机可追溯到IBM的VM/370,到上个世纪90年代,在计算机程序设计语言领域又出现一件革命性的事情——Java语言的出现,它与 ...

随机推荐

  1. java中的拷贝文件FileChannel

    以前用Java拷贝文件,只知道写byte数组循环拷贝,今天知道了可以用FileChannel进行拷贝,上代码: 下边是传统的byte数组拷贝方法 </pre><pre name=&q ...

  2. [转]Windows Shell 编程 第四章 【来源 http://blog.csdn.net/wangqiulin123456/article/details/7987933】

    第四章 文件的本质 以前,所有文件和目录都有一个确定的属性集:时间,日期,尺寸,以及表示‘只读的’,‘隐藏的,‘存档的’,或‘系统的’状态标志.然而,Windos95(及后来的WindowsNT4.0 ...

  3. __nonnull 和 __nullable (Swift 和 Objective-C混编)

    苹果在 Xcode 6.3 以后,为了解决 Swift 与 OC 混编时的问题,引入了一个 Objective-C 的新特性:nullability annotations. 这一新特性的核心是两个新 ...

  4. WPF 中,如何使用自定义的resources

    第一步,先自己自定义一个Resources 1.新建一个xaml文件,在其中自定义好自己的Resources 这个Resource 的根节点是 <ResourceDictionary xmlns ...

  5. English Audio-Books

    Downloadble English Audio-Books websites 一.网站 1.可听书 2.山寨 3.有声书库 4.audioboom.com 5.豆瓣小站 6.AudioBook 二 ...

  6. 生产者-消费者模型的3种Java实现:synchronized,signal/notifyAll及BlockingQueue

    我的技术博客经常被流氓网站恶意爬取转载.请移步原文:http://www.cnblogs.com/hamhog/p/3555111.html,享受整齐的排版.有效的链接.正确的代码缩进.更好的阅读体验 ...

  7. 如何自动拼接 Update语句,仅Update已修改的字段

    我们通常使用update语句更新数据库记录,例如使用update user set username='001', nickname='Tom', age=18 where id = 1语句更新use ...

  8. php的运行环境介绍

    php软件已下载在我的百度云:页面底部有地址,如有需要欢迎下载! 一:如何让php环境运行php代码? 直接使用php软件直接运行代码文件中的php代码 在B/S结构中让Apache使用php软件运行 ...

  9. msSQL数据库备份还原小结

    MSSQL自带了一个样例数据库pubs,就拿这个举例好了. 首先,来一次完全备份.对于数据量很大的数据库,这样的操作当然很费时间.所以我们采用每天凌晨4点一次完全备份,每个小时一个差异备份,每分钟一次 ...

  10. webApi实现增删改查操作

    1.WebApi是什么 ASP.NET Web API 是一种框架,用于轻松构建可以由多种客户端(包括浏览器和移动设备)访问的 HTTP 服务.ASP.NET Web API 是一种用于在 .NET ...