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

來源:互聯網
上載者:User

寫在前面: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[5]   The user cookie. Used by the application.

 **    meta[6]  

 **    meta[7]

 **    meta[8]

 **    meta[9]

1.2.4、讀取檔案頭
當應用程式調用API sqlite3_open開啟資料庫檔案時,SQLite就會讀取檔案頭進行資料庫的初始化。

int sqlite3BtreeOpen(
  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 */
){
//讀取檔案頭
  sqlite3pager_read_fileheader(pBt->pPager, sizeof(zDbHeader), zDbHeader);
  //設定頁面大小
pBt->pageSize = get2byte(&zDbHeader[16]);
//…
}

 

轉自:http://www.cnblogs.com/hustcat
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.