SQLite入門與分析 八 儲存模型 1

2022-03-12 11:00:19 字數 4925 閱讀 4955

寫在前面:sqlite作為嵌入式資料庫,通常針對的應用的資料量相對於通常dbms的資料量是較小的。所以它的儲存模型設計得非常簡單,總的來說,sqlite把乙個資料檔案分成若干大小相等的頁面,然後以b樹的形式來組織這些頁面。而對於大型的資料庫管理系統,比如oracle,或者dm ,儲存模型要複雜得多。就拿oracle來說吧,它對資料檔案不僅從物理進行分塊,而且從邏輯上進行分段,盤區和頁的乙個層次劃分,dm也一樣。不管怎麼說,資料庫檔案要儲存大量的資料,為了更好管理,查詢和運算元據檔案,dbms不得不從物理上、邏輯上對資料檔案的資料進行複雜的組織。本節主要討**件格式,下節討論頁面格式。

1、檔案格式

1.1、資料庫名稱

應用程式通過sqlite3_open  api來開啟資料庫,該函式的乙個引數為資料庫檔案的名稱。sqlite內部命名為main資料庫(除了臨時資料庫和記憶體資料庫)。sqlite對每乙個資料庫都建立乙個獨立的檔案。

在sqlite內部,資料檔名不是資料庫名。sqlite對應用程式的每乙個連線都維護著乙個單獨的臨時資料庫(temp資料庫),臨時資料庫存臨時物件,例如:表以及相應的索引。這些臨時物件僅僅對同乙個連線可見(對同乙個執行緒,程序的其它連線是不可見的),sqlite儲存臨時資料庫到乙個單獨的臨時檔案中,當應用程式關閉對main資料庫的連線時,就刪除臨時檔案。

1.2、資料庫檔案結構

除了記憶體資料庫,sqlite把乙個資料庫(main和temp)都儲存到乙個單獨的檔案。

1.2.1、頁面(page)

為了更好的管理和讀/寫資料庫,sqlite把乙個資料庫(包括記憶體資料庫)分成乙個個固定大小的頁面。頁面大小的範圍從512-32768(兩者都包含),頁面預設大小為1024個位元組(1kb),實際上,頁面的上限由2個位元組的有符號整數決定。整個資料庫可以看成這些頁面的陣列,頁面陣列的下標為頁面的編號(page number),page number從1開始,一直到2,147,483,647 (2^31– 1)。實際上,陣列上界還受檔案系統允許的最大檔案大小決定。0號頁面視為空頁面(null page),物理上不存在,1號頁面從檔案的0偏移處開始,乙個頁面接著下乙個頁面。

注:一旦資料庫建立,sqlite使用編譯時確定的預設的頁面大小。當然,在建立第乙個表之前,可以通過pragma命令改變頁面大小。sqlite把該值作為元資料的一部分儲存在檔案中。

1.2.2、頁面型別

頁面(page)分四種型別:葉子頁面(leaf),內部頁面(internal),溢位頁面(overflow)和空閒頁面(free)。內部頁面包含查詢時的導航資訊,葉子頁面儲存資料,例如元組。如果乙個元組的資料太大,乙個頁面容納不下,則一些資料儲存在b樹的頁面中,餘下的儲存在溢位頁面中。

1.2.3、檔案頭(file header)

作為檔案開始的1號頁面比較特殊,它包括100個位元組的檔案頭。當sqlite建立檔案時例初始化檔案頭,檔案頭的格式如下:

structure of database file header

offset

size

description

0 16

header string  

16 2

page size in bytes

18 1

file format write version  

19 1

file format read version

20 1

bytes reserved at the end of each page

21 1

max embedded payload fraction

22 1

min embedded payload fraction

23 1

min leaf payload fraction

24 4

file change counter

28 4

reserved for future use

32 4

first freelist page

36 4

number of freelist pages

40 60

15 4-byte meta values

示例資料(100個位元組):

53 51 4c 69 74 65 20 66 sqlite f

6f 72 6d 61 74 20 33 00 ormat 3.

04 00 01 01 00 40 20 20 .....@ 

00 00 00 11 00 00 00 00 ........

00 00 00 00 00 00 00 00 ........

00 00 00 01 00 00 00 01 ........

00 00 00 00 00 00 00 00 ........

00 00 00 01 00 00 00 00 ........

00 00 00 00 00 00 00 00 ........

00 00 00 00 00 00 00 00 ........

00 00 00 00 00 00 00 00 ........

00 00 00 00 00 00 00 00 ........

00 00 00 00

header string(頭字串):

16個位元組:"sqlite format 3."

page size:

頁面大小:0x04 00 ,即1024

file format:

檔案格式:0x01 ,0x01,在當前的版本都為1。

reserved space:

保留空間:0x00,1個位元組,sqlite在每個頁面的末尾都會保留一定的空間,留作它用,預設為0。

embedded payload:

max embedded payload fraction(偏移21)的值限定了b樹內節點(頁面)中乙個元組(記錄,單元)最多能夠使用的空間。255意味著100%,預設值為0x40,即64(25%),這保證了乙個結點(頁面)至少有4個單元。如果乙個單元的負載(payload,即資料量)超過最大值,則溢位的資料儲存到溢位的頁面,一旦sqlite分配了乙個溢位頁面,它會盡可能多的移動資料到溢位頁面,下限為min embedded payload fraction value(偏移為22),預設的值為32,即12.5% 。

min leaf payload fraction的含義與min embedded payload fraction類似,只不過是它是針對b樹的葉子結點,預設值為32,即12.5%,葉子結點最大的負載為通常是100%,這不用儲存。

file change counter:

檔案修改計數,通常被事務使用,它由事務增加其值。該值的主要目的是資料庫改變時,pager避免對快取進行刷盤。

freelist:

空閒頁面鍊錶,在檔案頭偏移32的4個位元組記錄著空閒頁面鏈的第乙個頁面,偏移36處的4個位元組為空閒頁面的數量。空閒頁面鍊錶的組織形式如下:

空閒頁面分為兩種頁面:trunk pages(主頁面)和leaf  pages(葉子頁面)。檔案頭的指標指向空閒鍊錶的第乙個trunk page,每個trunk page指向多個葉子頁面。

trunk page的格式如下,從頁面的起始處開始:

(1)4個位元組,指向下乙個trunk page的頁面號;

(2)4個位元組,該頁面的葉子頁面指標的數量;

(3)指向葉子頁面的頁面號,每項4個位元組。

當乙個頁面不再使用時,sqlite把它加入空閒頁面鍊錶,並不從本地檔案系統中釋放掉。當新增新的資料到資料庫時,sqlite就從空閒鍊錶上取出空閒頁面用來在儲存資料。當空閒鍊錶為空時,sqlite就通過本地檔案系統增加新的頁面,新增到資料庫檔案的末尾。

注:可以通過vacuum命令刪除空閒鍊錶,該命令通過把資料庫中資料拷貝到臨時檔案,然後在事務的保護下,用臨時檔案中的複本覆蓋原資料庫檔案。

meta variables

元資料變數:從偏移為40開始,為15個4位元組的元資料變數,這些元資料主要與b樹和vm有關。如下:

** meta values are as follows:

**meta[0]   schema cookie. changes with each schema change.

**meta[1]   file format of schema layer.

**meta[2]   size of the page cache.

**meta[3]   use freelist if 0. autovacuum if greater than zero.

**meta[4]   db text encoding. 1:utf-8 2:utf-16le 3:utf-16be

**meta[6]  

**meta[7]

**meta[8]

**meta[9]

1.2.4、讀取檔案頭

當應用程式呼叫api sqlite3_open開啟資料庫檔案時,sqlite就會讀取檔案頭進行資料庫的初始化。

intsqlite3btreeopen(

const

char

*zfilename,  

/*name of the file containing the btree database 

*/sqlite3 

*psqlite,       

/*associated database handle 

*/btree 

**ppbtree,        

/*pointer to new btree object written here 

*/int

flags               

/*options */)

**:

SQLite入門與分析 二 設計與概念 續

寫在前面 本節討論事務,事務是dbms最核心的技術之一.在計算機科學史上,有三位科學家因在資料庫領域的成就而獲acm圖靈獎,而其中之一jim gray 曾任職微軟 就是因為在事務處理方面的成就而獲得這一殊榮,正是因為他,才使得oltp系統在隨後直到今天大行其道.關於事務處理技術,涉及到很多,隨便就能...

SQLite入門與分析 二 設計與概念 續

寫在前面 本節討論事務,事務是dbms最核心的技術之一.在計算機科學史上,有三位科學家因在資料庫領域的成就而獲acm圖靈獎,而其中之一jim gray 曾任職微軟 就是因為在事務處理方面的成就而獲得這一殊榮,正是因為他,才使得oltp系統在隨後直到今天大行其道.關於事務處理技術,涉及到很多,隨便就能...

SQLite入門與分析 二 設計與概念 續

寫在前面 本節討論事務,事務是dbms最核心的技術之一.在計算機科學史上,有三位科學家因在資料庫領域的成就而獲acm圖靈獎,而其中之一jim gray 曾任職微軟 就是因為在事務處理方面的成就而獲得這一殊榮,正是因為他,才使得oltp系統在隨後直到今天大行其道.關於事務處理技術,涉及到很多,隨便就能...