2015年8月27日 星期四

SQLite 簡介

資料庫在處理大量的資料上是很必要的,但如果資料固定且量不多,或是資料庫只會在單機上使用,且沒有讓多人使用的需求的話,就不一定需要特別架一個資料庫系統;因此,可以使用類似 SQLite 這樣的嵌入式資料庫(embedded SQL database)。

SQLite 的資料庫(database)都是以單一檔案的形式存於磁碟中,不需要再安裝資料庫伺服器軟體,所以要把資料庫複製或建立在你的電腦上是相單簡單快速。
SQLite 是一個很小的 C 語言程式庫,且本身就完全包含資料庫引擎的功能,而且可以嵌入至其他程式中,完全不用額外的設定。

特性如下:
  • 支援ACID (Atomic, Consistent, Isolated, Durable) transaction。
  • Zero-configuration:無須管理者的設定及管理。
  • 支援大部分SQL92的語法。
  • 資料庫存在於一個單一的檔案中。
  • 資料庫系統所在機器的位元組順序(Byte order)無關。
  • 支援大小至2 terabytes (2^41 bytes)。
  • 記憶體需求小:小於3萬行的C語言程式碼。小於250KB的程式空間。
  • 大部分的資料庫操作皆快於一般資料庫系統。
  • 簡單易用的API。
  • 支援TCL。也有其他語言的支援可用。
  • 註解詳細的程式碼,以及超過90%的測試。
  • 程式庫自己包含完整的功能,無須其他額外的程式或程式庫。
  • 為public domain,可免費使用。
  • serverless
  • cross-platform - 使用unicode
  • 不會進行data type檢查


架构(architecture)
SQLite采用了模块的设计,它由三个子系统,包括8个独立的模块构成。
接口(Interface) 接口由SQLite C API组成,也就是说不管是程序、脚本语言还是库文件,最终都是通过它与SQLite交互的(我们通常用得较多的ODBC/JDBC最后也会转化为相应C API的调用)。 
编译器(Compiler) 在编译器中,分词器(Tokenizer)和分析器(Parser)对SQL进行语法检查,然后把它转化为底层能更方便处理的分层的数据结构---语法树,然后把语法树传给代码生成器(code generator)进行处理。而代码生成器根据它生成一种针对SQLite的汇编代码,最后由虚拟机(Virtual Machine)执行。 
虚拟机(Virtual Machine) 架构中最核心的部分是虚拟机,或者叫做虚拟数据库引擎(Virtual Database Engine,VDBE)。它和Java虚拟机相似,解释执行字节代码。VDBE的字节代码由128个操作码(opcodes)构成,它们主要集中在数据库操作。它的每一条指令都用来完成特定的数据库操作(比如打开一个表的游标)或者为这些操作栈空间的准备(比如压入参数)。总之,所有的这些指令都是为了满足SQL命令的要求(关于VM,后面会做详细介绍)。 
后端(Back-End) 后端由B-树(B-tree),页缓存(page cache,pager)和操作系统接口(即系统调用)构成。B-tree和page cache共同对数据进行管理。B-tree的主要功能就是索引,它维护着各个页面之间的复杂的关系,便于快速找到所需数据。而pager的主要作用就是通过OS接口在B-tree和Disk之间传递页面。

事务(Transaction)
事务的周期(Transaction Lifecycles) 
程序与事务之间有两件事值得注意: 
A、哪些对象在事务下运行——这直接与API有关。 
B、事务的生命周期,即什么时候开始,什么时候结束以及它在什么时候开始影响别的连接(这点对于并发性很重要)——这涉及到SQLite的具体实现。 
一个连接(connection)可以包含多个狀態(statement),而且每个连接有一个与数据库关联的B-tree和一个pager。Pager在连接中起着很重要的作用,因为它管理事务、锁、内存缓存以及负责崩溃恢复(crash recovery)。当你进行数据库写操作时,记住最重要的一件事:在任何时候,只在一个事务下执行一个连接。这些回答了第一个问题。 
一般来说,一个事务的生命和statement差不多,你也可以手动结束它。默认情况下,事务自动提交,当然你也可以通过BEGIN..COMMIT手动提交。接下来就是锁的问题。
关于这个图有以下几点值得注意: 
A、一个事务可以在UNLOCKED,RESERVED或EXCLUSIVE三种状态下开始。默认情况下在UNLOCKED时开始。 
B、白色框中的UNLOCKED, PENDING, SHARED和 RESERVED可以在一个数据库的同一时存在。 
C、从灰色的PENDING开始,事情就变得严格起来,意味着事务想得到排斥锁(EXCLUSIVE)(注意与白色框中的区别)。 
虽然锁有这么多状态,但是从体质上来说,只有两种情况:读事务和写事务。

SQL语法    由于以前用SQLServer或者ISeries,所以DDL的语法很汗颜 
   创建一个单个Primary Key的table    CREATE TABLE  [Admin] ( 
             [UserName] [nvarchar] (20)   PRIMARY KEY NOT NULL , 
             [Password] [nvarchar] (50)   NOT NULL , 
             [Rank] [smallint] NOT NULL , 
             [MailServer] [nvarchar] (50)   NOT NULL , 
             [MailUser] [nvarchar] (50)   NOT NULL , 
             [MailPassword] [nvarchar] (50)   NOT NULL , 
             [Mail] [nvarchar] (50)   NOT NULL 
   ) ; 
  创建一个多个Primary Key的table    CREATE TABLE  [CodeDetail] ( 
             [CdType] [nvarchar] (10)  NOT NULL , 
             [CdCode] [nvarchar] (20)  NOT NULL , 
             [CdString1] [ntext]   NOT NULL , 
             [CdString2] [ntext]   NOT NULL , 
             [CdString3] [ntext]   NOT NULL, 
              PRIMARY KEY (CdType,CdCode) 
   ) ; 
  创建索引    CREATE  INDEX [IX_Account] ON  [Account]([IsCheck], [UserName]); 
   还可以视图等等。

SQLite 分页查询
寫法1:    SELECT * FROM TABLE1 LIMIT  20 OFFSET 20 ;
寫法2:    SELECT * FROM TABLE1 LIMIT 20 , 20;

SQLite 文件的压缩 
在多次删除数据、插入数据、更新数据后,数据库体积增大,但实际有效数据量很小,则需要对数据库进行压缩、整理,把已经删除的数据从物理文件中移除。调用一下SQL命令即可:
VACUUM
VACUUM的实现

数据插入与更新
使用REPLACE替代INSERT、UPDATE命令。在无满足条件记录,则执行Insert,有满足条件记录,则执行UPDATE。
REPLACE INTO TABLE1(col1, col2, col3) VALUES(val1, val2,val3);
Insert or Replace Into 和Replace Into 的效果是一样的上面这句话也可以这样写
Insert or Replace INTO TABLE1(col1, col2, col3) VALUES(val1, val2,val3);

沒有留言:

張貼留言