SQLite使用(一)&&选择表类型
在SQLite中,主要有两种表类型,带rowid的表和不带rowid的表。我们利用create table 建一张表,默认都会有一个隐含名字为rowid的主键,暂且称带rowid的表为普通表。如果建表时指定 WITHOUT ROWID属性,那么建的表就是不带rowid的表。那么这两种表有什么区别?这篇文章主要讨论这两种表的存储实现,以及它们的优缺点和适用的应用场景。
1.rowid是什么?
SQLite中rowid是一个隐身存储的列,8个字节存储,它有两个别名 _ROWID_ 和 OID,类型定义为INTEGER PRIMARY KEY,因此当用户建表时,某列定义为 INTEGER PRIMARY KEY,实质是rowid的别名。rowid是自增的,当该列插入null时, 会取当前表的最大值+1,作为该列的值。注意INTEGER与int不同,比如若列定义为 int primary key, 则插入null值,该列的值就是null,rowid依然会递增。查询可以通过select rowid from tablename得到rowid的值。为什么INTEGER与int不同,可以参考SQLite数据类型。
2.AUTOINCREMENT属性
在SQLite中,AUTOINCREMENT属性只能用于定义为INTEGER PRIMARY KEY的列,否则建表时会报错。没有AUTOINCREMENT属性的rowid始终取当前最大值+1,若删除了最大rowid所在的记录,导致这个rowid会重用。 采用AUTOINCREMENT属性可以避免重用情况,系统内部通过sqlite_sequence表来维护每个表的最大sequence值, 因此即使有删除情况,也不会导致rowid重用,严格单调递增,代价是执行插入时, 需要维护sqlite_sequence表,对性能有一定的损耗。 由于rowid采用8个字节存储,因此上限值为9223372036854775807,当超过这个值时,rowid属性会随机选择一个值, 只要不与表中已有记录冲突即可;而AUTOINCREMENT属性则会提示Error: database or disk is full。
3.存储区别
普通表的PRIMRAY KEY实质是一个唯一索引,表数据按rowid组织(聚集索引), 通过主键访问表,实质需要访问唯一索引和聚簇索引,但对于INTEGER PRIMARY KEY除外, 它是rowid的一个别名,索引实质就是聚簇索引。在SQLite中,聚集索引采用B*树存储(B*树是B+的一个特例,非叶子节点间也通过双向指针相连),而普通索引(二级索引,唯一索引)采用B-树存储,B+树与B树的区别在于,B+树中非叶子节点只有key信息,叶子节点包含了key和value信息,并且叶子节点包含了所有key信息,key信息在叶子节点和非叶子节点存储了两遍,叶子节点间有双向指针相连;而B-树中,叶子节点和非叶子节点结构相同,都包含了key和value信息,查找可能在非叶子节点找到数据,直接返回。
WITHOUT ROWID表采用B-Tree,叶子节点和非叶子节点都有记录所有内容, 因此若记录较长(超过page_size*1/20),扇出(节点记录数)很小,容易造成节点频繁分裂,不适合使用WITHOUT ROWID属性, 。WITHOUT ROWID 表只有一颗B-树,访问只需要访问一次B-树, 而普通表需要访问两次(索引+表),对于INTEGER PRIMARY KEY除外。WITHOUT ROWID不支持AUTOINCREMENT属性,并且PRIMARY KEY不能为null,普通表比较变态,PRIMARY KEY 属性列也可以为null(由于历史原因,没有修改)。
4. 例子
(1).普通表
CREATE TABLE IF NOT EXISTS wordcount1(
word TEXT PRIMARY KEY,
cnt INTEGER
);
wordcount1是一个普通表,底层采用两颗B树存储,一颗B*树存储的是表内容,key为rowid,value为(word,cnt);另一颗B-树是主键索引,key为(word,rowid)。因此对于每个word,都会在两颗B树中分别存一次。假设我们要查询word为"xyzzy"的记录:
SELECT cnt FROM wordcount1 WHERE word='xyzzy';
为了得到结果,首先需要通过主键索引找到rowid,然后再以rowid为key查找表,得到cnt,总共需要查找两次B树。
(2).WITHOUT ROWID表
CREATE TABLE IF NOT EXISTS wordcount2(
word TEXT PRIMARY KEY,
cnt INTEGER
) WITHOUT ROWID;
wordcount2是WITHOUT ROWID表,底层只有一颗B-树,即主键索引,相对于wordcount1表,wordcount2表中word只需存储一次。如果查询word为"xyzzy"的记录,只需查找一颗B树即可。因此在这种情况下,WITHOUT ROWID表不仅节省了存储,而且查询效率也比普通表效率高。
4.如何选择表类型?
1) 若主键为整型,采用普通表,将列定义为INTEGER PRIMARY KEY,这样保证只有只有1颗B*树,提高查询效率;
2) 若主键为非整型,记录比较小(不超过page_size*1/20),并且不依赖于rowid的逻辑序号,可以考虑使用WITHOUT ROWID表,节省空间 的同时,提高查询效率
3) 其它情况,则使用普通表,定义主键。
5.参考文档
https://www.sqlite.org/withoutrowid.html
SQLite使用(一)&&选择表类型的更多相关文章
- mysql————表类型(存储引擎)的选择
表类型(存储引擎)的选择 7.1 mysql存储引擎概述 插件式存储引擎是mysql数据库最重要的特性之一,用户可以根据应用的需要选择ruhr存储和索引数据,是否使用事务等. InnoDB和BDB提供 ...
- 浅谈MySql的存储引擎(表类型)
来源:http://www.cnblogs.com/lina1006/archive/2011/04/29/2032894.html 什么是MySql数据库 通常意义上,数据库也就是数据的集合,具体到 ...
- mysql如何修改表类型(表引擎)
参考阅读:http://www.manongjc.com/article/1205.html 最近遇到一个修改 MySQL 表类型的问题,以前在 phpmyadmin 管理 mysql 数据库时,建立 ...
- MySQL表类型
学习Mysql数据库,Mysql表类型都有哪些是一定需要知道的,下面就为您介绍七种Mysql表类型,希望能对您学习Mysql表类型有所帮助. MySQL作为当前最为流行的免费数据库服务引擎,已经风靡了 ...
- 浅谈MySql的存储引擎(表类型) (转)
什么是MySql数据库 通常意义上,数据库也就是数据的集合,具体到计算机上数据库可以是存储器上一些文件的集合或者一些内存数据的集合. 我们通常说的MySql数据库,sql server数据库等等其实是 ...
- InnoDB的表类型,逻辑存储结构,物理存储结构
表类型 对比Oracle支持的各种表类型,InnoDB存储引擎表更像是Oracle中的索引组织表(index organized table).在InnoDB存储引擎表中,每张表都有个主键,如果在创建 ...
- 第三章(附)mysql表类型MyISAM和InnoDB区别(决定了是否支持事务)
mysql表类型MyISAM和InnoDB区别 MyISAM:这个是默认类型,它是基于传统的ISAM类型,ISAM是Indexed Sequential Access Method (有索引的顺序访问 ...
- MySQL常用的七种表类型(转)
MySQL常用的七种表类型(转) 其实MySQL提供的表类型截至到今天已经有13种,各有各的好处,但是民间流传的常用的应该是7种,如果再细化出来,基本上就只有两种:InnoDB.MyIASM两种. ...
- Oracle12c 性能优化攻略:攻略1-3: 匹配表类型与业务需求
注:目录表 <Oracle12c 性能优化攻略:攻略目录表> 问题描述 你刚开始使用oracle数据库,并且学习了一些关于可用的各种表类型的知识.例如:可以在堆组织表.索引组织表等之间支出 ...
随机推荐
- 微软消息分析器(Microsoft Message Analyzer )更新至1.2版-2015-1-20
就在刚才,收到了微软Connect的邮件推送,大名鼎鼎的微软消息分析器更新至1.2版,并且有公众下载链接,大家可以在这里进行下载. 这里简单摘录一下博客里面提到的新版所增加的功能与功能的改进方面. G ...
- 恢复SharePoint Server 2013 中的“新颖快建视图”
初始化后就很漂亮的"新颖快建视图" 在配置好了OWA(Office Web Apps)的环境下,可以使用独特的"新颖快建视图"新建文件与文件夹,如下图所示: F ...
- 常见ArcGIS操作(以10.0为例)
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.建立缓冲区 先在图层属性表里面新建一个缓冲区半径字段,然后对该字段赋 ...
- SDN/NFV若干问题
1.首先谈一谈网络技术和组网技术的关系 网络可分为两层:业务网.承载网.业务网主要是组织业务系统,而承载网主要是用来传输信息流:包括传送网(点到点数据专线).数据网(端到端连接).内容分发网(点到多点 ...
- Easyui datagrid editor为combobox时指定数据源
当在datagrid行内部应用添加编辑操作时,引入combobox是非常方便的操作,我在引入combobox时对数据源这快做个总结,在做demo的过程中遇到个问题,就是当你选择了下拉框的值后点击保存, ...
- 搭建OpenGL环境-Windows/VS2013
对于opengl的环境,简单搭建的话其实和opencv差不多,你会看到下面的过程与opencv类似,不同的就是某些文件需要自己找(因为不是集成的,各个拓展需要单独下载) 1.首先,对于opengl头文 ...
- 使用代码为textview设置drawableLeft
xml中的textView中设置android:drawableLeft: <TextView android:id="@+id/bookTitle" android:lay ...
- Equals和ReferenceEquals
稍微分析下一下两个方法的区别: public static bool Equals(object objA, object objB); public static bool ReferenceEqu ...
- ECMAScript 5中属性的特性值
这是<JavaScript高级程序设计(第三版)>第六章相关内容的总结. ECMAScript中有两种属性:数据属性和访问器属性.每种属性都有四个特性值. 数据属性的四个特性值: [[Co ...
- PHP+MySQL中实现分页
你只需要在需要添加页的页面加入这几行代码 <?phpinclude 'form.class.php'; $p=new Page(100, 'Demo01.php');//这里需要传递两个参数,参 ...