我对SQLite的强行研究

写在前面
本文是我之前对SQLite的学习分享PPT的一次整理,文末附带PPT与源码的GitHub下载地址

我对SQLite的强行研究_第1张图片
嵌入式关系型数据库SQLite

存储类型

五种存储类型:blob、text、real、integer以及null

  • blob
    二进制对象,最大长度可自定义,默认为1000,000,000 字节
  • text
    字符数据,支持UTF-8、UTF-16,字符串最大长度可被设置,默认为1000000000 字节
  • real


    8字节浮点数范围
  • integer
    1、2、3、4、6、8字节
  • null
    空值
我对SQLite的强行研究_第2张图片
存储类型

SQLite不存在数据类型的限制,只有存储类型的区别。比如,向一个text存储类型的字段插入浮点数值,SQLite将进行自动转换,SQLite内置函数typeof()根据值返回对应存储类型,比如select typeof(‘3.14’);将返回类型text

类型的相互转换

blob text real integer null
blob -- 需要时加上\000终止符 转换为文本,atoi 转换为文本,atoi --
text 原文 -- atoi atoi --
real 浮点数ASCII码 浮点数ASCII码 -- 浮点型转整型 --
integer 整数ASCII码 整数ASCII码 整型转浮点型 -- --
null null指针 null指针 0.0 0 --

亲缘类型

为了和其他DBMS以及SQL标准兼容,在CREATE TABLE中指定列类型,SQLite提出列相似性(Column Affinity)的概念,即列的属性或叫亲缘类

声明类型 亲缘类 转换规则
INT、INTEGER、TINYINT、SMALLINT、MEDIUMINT、BIGINT、UNSIGNED BIG INT、INT2、INT8 INTEGER 如果类型字符串中包含"INT",那么该字段的亲缘类型是INTEGER
CHARACTER(20)、VARCHAR(255)、VARYING、CHARACTER(255)、NCHAR(55)、NATIVE、CHARACTER(70)、NVARCHAR(100)、TEXT、CLOB TEXT 如果类型字符串中包含"CHAR"、"CLOB"或"TEXT",那么该字段的亲缘类型是TEXT,如VARCHAR
BLOB NONE 如果类型字符串中包含"BLOB",那么该字段的亲缘类型是NONE
REAL、DOUBLE、DOUBLE PRECISION、FLOAT REAL 如果类型字符串中包含"REAL"、"FLOAT"或"DOUBLE",那么该字段的亲缘类型是REAL
NUMERIC、DECIMAL(10,5)、BOOLEAN、DATE、DATETIME NUMERIC 其余情况下,字段的亲缘类型为NUMERIC

事务性

命令:begin、commit、rollback

隐式自成事务

默认情况下,SQLite单条SQL语句自成事务(自动提交)


我对SQLite的强行研究_第3张图片
操作A自成事务

显式事务

由begin和commit之间的一组操作组成一项事务
事务性保证了一项操作或一组操作,要么100%完成,要么全部没有执行

// 示例:
begin;
DELETE FROM test WHERE id = 5;
rollback;
DELETE FROM test WHERE goal = 88;
commit;
我对SQLite的强行研究_第4张图片
操作A没有完成,操作B完成

事务的冲突解决

命令:replace、ignore、fail、abort、rollback


我对SQLite的强行研究_第5张图片
事务的冲突解决
冲突解决 说明
replace 违反的记录被删除,以新记录代替之
ignore 违反的记录保持原貌,其它记录继续执行
fail 终止命令,违反之前执行的操作得到保存
abort 终止命令,恢复违反之前执行的修改
rollback 终止命令和事务,回滚整个事务

语法:

  1. 语句级(可覆盖对象级的冲突解决手段)
    insert/update/create or [resolution] table/index [tbl_name/idx_name] ……
    [resolution]: replace、ignore、fail、abort、rollback

  2. 对象级(定义表格时)
    create table/index [tbl_name/idx_name] ([field_name] [format] [constraint] on conflict [resolution]);
    [constraint]:unique、not null……

// 示例
create temp table cast (name text unique on conflict rollback);
insert into cast values (‘Jerry’);
insert into cast values (‘Bean’);
insert into cast values (‘Android 4.1’);

begin;
insert into cast values (‘Jerry’);
:uniqueness constraint failed
commit;
:cannot commit – no transaction is active

begin;
insert or replace into cast values (‘Jerry’);
commit;

锁机制

五种锁状态:unlocked、shared、reserved、pending、exclusive

锁状态 说明
未加锁-unlocked 未对数据库进行访问(读写)之前
共享锁-shared 对数据库进行读操作
预留锁-reserved 对数据库进行写(缓存)操作
未决锁-pending 等待其它共享锁关闭
排它锁-exclusive 将缓存中的操作提交到数据库
我对SQLite的强行研究_第6张图片
红色箭头代表你,你想访问数据库DB
我对SQLite的强行研究_第7张图片
红色箭头代表你,你受锁机制的约束
我对SQLite的强行研究_第8张图片
死锁原因

死锁原因:拥有共享锁与未决锁的连接都不想放弃控制

预防死锁

三种事务类型:deferred、immediate、exclusive
SQLite根据不同的事务类型,以不同的锁状态启动事务(而不是以未加锁状态启动)

事务类型在begin命令中指定:
begin [deferred | immediate | exclusive] transaction;

事务类型 说明
Deferred 直到必须使用时才获取锁
Immediate 在begin执行时试图获取预留锁
Exclusive 试图获取排它锁

基本准则,多人对同一数据库进行操作时,必须共同遵守本守则:
使用begin immediate | exclusive transaction;而不是begin deferred transaction;或单纯的begin;

SQLite不支持ANSI SQL92的部分特性

  • 右外连接与全外连接
    支持左外连接 LEFT OUTER JOIN
    不支持右外连接 RIGHT OUTER JOIN 和全外连接 FULL OUTER JOIN
  • 大部分的修改表操作
    支持 RENAME TABLE 和 ADD COLUMN
    不支持 DROP COLUMN、ALTER COLUMN、ADD CONSTRAINT
  • 触发器
    支持 FOR EACH ROW 触发器
    不支持 FOR EACH STATEMENT 触发器
  • 授权与撤销
    不支持 GRANT 和 REVOKE,它们对于嵌入式数据库引擎无意义
    SQLite 读取和写入一个普通磁盘文件
    唯一的访问许可对于底层操作系统的一般文件有效

工作模式

main db temp db 创建方式 存储位置
磁盘文件 默认 create temp table “path/db_name” 磁盘
驻留内存 默认 create temp table “:memory:” or “” RAM

使用命令sqlite3创建一个数据库文件

  • 默认存在main数据库对象,所有默认操作都是在main数据库对象中进行
  • 若执行了CREATE TEMP TABLE命令,该数据库文件将连接一个temp数据库对象
  • 若执行ATTACH命令,该数据库文件连接一个外部的数据库对象

配置

SQLite没有配置文件
所有的配置参数都是靠编译指令PRAGMA或编译时参数定义来实现
运行信息、schema、版本、 文件格式、内存使用和调试等可供配置
编译指令包括临时性和永久性两种
1)PRAGMA
2)编译时参数(宏)

PRAGMA

1)连接缓冲区大小
PRAGMA cache_size;
PRAGMA default_cache_size;

2)数据库信息获取
PRAGMA database_list;
PRAGMA foreign_key_list(table-name);
PRAGMA index_info(index-name);
PRAGMA index_list(table-name);
PRAGMA table_info(table-name);

3)写同步
PRAGMA synchronous; // 影响非常大的优化设置

4)临时存储器
PRAGMA temp_store;
PRAGMA temp_store_directory;

5)页大小、编码和自动清理
PRAGMA page_size;
PRAGMA encoding;
PRAGMA auto_vacuum; // 开启后手动vacuum命令将不起作用

6)调试
PRAGMA integrity_check; // 完整检查,无误返回ok

1)SQLITE_TEMP_STORE
等于0时,临时文件总是存储在磁盘上,而不会考虑PRAGMA temp_store指令的设置。
等于1时,临时文件缺省存储在磁盘上,但该值可以被PRAGMA temp_store指令覆盖。
等于2时,临时文件缺省存储在内存中,但该值可以被PRAGMA temp_store指令覆盖。
等于3时,临时文件总是存储在内存中,而不会考虑PRAGMA temp_store指令的设置。

我对SQLite的强行研究_第9张图片
SQLite工作模式配置

2)SQLITE_DEFAULT_TEMP_CACHE_SIZE
用于指定临时表和索引在占用多少Cache Page时才需要被刷新到磁盘文件
该参数的缺省值为500页

谨慎使用temp_store_directory修改临时文件存储目录!!!
对于Unix/Linux/OSX来说,默认可路径是/var/tmp, /usr/tmp, /tmp以及当前目录 current-directory中第一个可写的目录。对于 WINDOWS NT,默认路径由WINDOWS决定,通常是C:\Documents and Settings\user-name\Local Settings\Temp\。SQLite创建的临时文件在打开后会被立即删除(unlink), 这样当SQLite进程退出时,操作系统就可以自动删除这些文件。所以正常状态下,使用ls或dir命令是无法看到这些临时文件的。

C API

两个重要的对象

我对SQLite的强行研究_第10张图片
两个重要的对象
  • database connection
    数据库连接对象 sqlite3,即数据库名
  • prepared statement
    预声明对象 sqlite3_stmt,简单理解就是指向 SQL 命令的一个结构

六个接口

我对SQLite的强行研究_第11张图片
六个接口

(1)使用sqlite3_open()连接一个数据库,一个连接访问多个数据库使用attach功能。
(2)使用sqlite3_prepare()创建prepared statement对象。
(3)调用sqlite3_step()执行prepared statement一次或多次。
(4)查询时,在两个sqlite3_step()调用之间调用sqlite3_column()解压结果。
(5)使用sqlite3_finalize()销毁prepared statement对象。
(6)调用sqlite3_close()关闭数据库连接。

封装接口

我对SQLite的强行研究_第12张图片
封装接口

sqlite3_exec():适合执行不返回结果集的查询,它将结果交给callback函数处理
sqlite3_get_table():适合执行返回结果集的查询,它将结果存储在堆内存中而不是交给callback函数处理

多次查询

我对SQLite的强行研究_第13张图片
多次查询
我对SQLite的强行研究_第14张图片
多次查询

sqlite3_exec():执行不返回结果集的查询
sqlite3_get_table():执行返回结果集的查询

性能

测试目的

(1)了解SQLite文件模式与内存模式的插、查、删、递归速度
(2)了解SQLite文件模式与内存模式的操作稳定性

测试项目

(1)SQLite文件模式与内存模式的插、查、删、递归速度测试
(2)SQLite文件模式与内存模式的操作稳定性测试

常规操作性能测试

我对SQLite的强行研究_第15张图片
测试样例

测试项目:
文件模式插入100万条记录
内存模式插入100万条记录
文件模式递归100万条记录
内存模式递归100万条记录
文件模式查询1000 条记录
内存模式查询1000 条记录
文件模式删除100万条记录
内存模式删除100万条记录

测试版本:
SQLite V3.7.13

我对SQLite的强行研究_第16张图片
结果

稳定性测试

以文件模式分别测试插入、查询、删除与递归在记录量为
10万、20万……100万的时间性能,
得到大致的时间性能曲线。

以内存模式分别测试插入、删除与递归在记录量为
100万、200万……1000万的时间性能各三次,
得到大致的时间性能稳定性曲线。

我对SQLite的强行研究_第17张图片
内存插入
我对SQLite的强行研究_第18张图片
内存删除
我对SQLite的强行研究_第19张图片
内存递归
我对SQLite的强行研究_第20张图片
文件插入
我对SQLite的强行研究_第21张图片
文件删除
我对SQLite的强行研究_第22张图片
文件递归

老规矩-PPT及测试代码下载地址

GitHub地址

关于SQLite的学习资料

1.官网文档
2.重点推荐这本书《SQLite权威指南》
3.SQLite中文社区
4.SQLite维基
5.博客园

你可能感兴趣的:(我对SQLite的强行研究)