您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“SQLite數據庫的工作原理分析”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“SQLite數據庫的工作原理分析”這篇文章吧。
SQLite 是一個小型數據庫應用程序,用于數百萬個軟件和設備。SQLite 是由 D.Richard Hipp 于 2000 年 8 月發明的。SQLite 是一種高性能、輕量級的關系數據庫。如果您愿意在編碼級別學習數據庫的內部結構,那么 SQLite 是最好的開源數據庫,它具有高度可讀的源代碼和大量文檔。閱讀更高版本的 SQLite 變得有點困難,因為它包含許多新功能。為了理解數據庫內部的基本實現,你應該對數據結構有很好的了解,一些關于計算理論的知識,以及操作系統是如何工作的。
在這里,我們將研究 SQLite 2.5.0 版本。您可以在GitHub上找到SQLite 后端的簡單實現。 另外,我發現這個存儲庫 包含用于代碼讀取的 SQLite 2.5.0 實現。
將數據保存在平面文件中讀取和存儲數據的效率不高。數據庫以適當的順序組織數據,以便數據讀取和寫入速度更快。數據可以是結構化的、半結構化的或非結構化的。數據庫主要用于存儲結構化和半結構化數據。可以根據要存儲的數據結構類型對數據庫進行如下挖掘。
關系型數據庫:常用的具有表結構的數據庫類型。表可以與其他表有關系。SQL 語言用于操作此類數據庫上的數據。
鍵值數據庫:與關聯的鍵一起存儲的數據。可以使用給定的鍵檢索數據。內存數據庫通常是這種類型的數據庫。
對象數據庫:數據結構更像是一個對象而不是一個表。
圖數據庫:圖數據庫是節點和邊的集合,主要用于數據挖掘和社交媒體應用程序。
SQLite 數據庫架構分為兩個不同的部分,分別命名為核心和后端。核心部分包含接口、分詞器、解析器、代碼生成器和虛擬機,它們為數據庫事務創建執行順序。后端包含 B-tree、Pager 和 OS 接口來訪問文件系統。Tokenizer、Parser 和代碼生成器統稱為編譯器,它生成一組運行在虛擬機上的操作碼。
要了解數據庫的架構,您需要具備以下先決條件。
對數據結構和算法有很好的理解。尤其是 B 樹、鏈表、Hashmaps 等數據結構。
對計算機體系結構有一定的了解。如何讀寫磁盤,分頁和緩存如何工作。
有限自動機、上下文無關語法等理論計算機和一些正則表達式知識。
Unix 和 Windows 上的文件訪問彼此不同。VFS 提供通用 API 來訪問文件,而無需考慮其運行的操作系統類型。該 API 包括打開、讀取、寫入和關閉文件的函數。以下是 VFS 中用于讀取、寫入數據到文件中的一些 API。
/*
Create a connection to file to read write
zFilename : file name
id : file pointer
pReadonly : read or write
*/
int sqliteOsOpenReadWrite(const char *zFilename, OsFile *id,int *pReadonly);
/*
Acqure the lock to read file. This function should be
called before caling to any file read function.
Return 0 if success
id : file pointer
*/
int sqliteOsReadLock(OsFile *id);
/*
Get the write lock to write into a file. This function should called before
doing any write operation into the file system.
Return 0 if success
id : file pointer
*/
int sqliteOsWriteLock(OsFile *id);
/*
Move to the given number of offest to read or write into the file
*/
int sqliteOsSeek(OsFile *id, int offset);
/*
Read amt bytes from the file with offset pointed by sqliteOsSeek
*/
int sqliteOsRead(OsFile *id, void *pBuf, int amt);
/*
Write amt bytes from the pBuf into the file
*/
int sqliteOsWrite(OsFile *id, const void *pBuf, int amt);
在這里,您可以使用 sqliteOpenReadWrite 函數開始使用文件。此函數為您提供一個指向文件的指針,該文件可用于讀取或寫入數據。接下來,應該在執行任何讀寫操作之前獲取鎖。如果它只是一個讀操作,那么應該獲取讀鎖。應該為讀和寫事務獲取寫鎖。
然后可以通過將文件的偏移量提供給 sqliteOsSeek 函數來查找位置來完成讀寫。偏移量是從文件的起點到數據應該寫入或讀取的位置的字節數。
頁是文件系統上數據庫事務的最小單位。當數據庫需要從文件中讀取數據時,它會將它作為一個頁面來請求。一旦頁面被加載到數據庫引擎中,如果它經常訪問它的緩存,它就可以存儲該頁面。頁數從一頁開始編號。第一個頁面稱為根頁面。頁的大小是恒定的。
/*
Open pager with the given file name
*/
int sqlitepager_open(Pager **ppPager,const char *zFilename,int nPage,int nEx);
/*
Get page specified by the page number
*/
int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage);
/*
Start to write data into a page specified in pData
*/
int sqlitepager_write(void *pData);
/*
Commit page changes into the file
*/
int sqlitepager_commit(Pager*);
/*
Close the connection to the file
*/
int sqlitepager_close(Pager *pPager);
Btree 是一種數據結構,用于根據數據的值將數據存儲為樹。BTree 最簡單的形式是二叉樹。數據庫使用 Btree 數據結構來存儲索引以提高數據庫的性能。Btree 的每個節點都包含一個用于索引的鍵列表。可以為表中的每一列創建 Btree 索引。每個 Btree 都有根頁面,這是任何 Btree 搜索的起點。
為了指向 Btree 上的一行,使用了稱為“Cursor”的特殊指針。游標用于指向一個記錄,該記錄由頁面 id 和偏移量指定,稱為 idx。SQLite 將數據庫模式存儲在稱為“master_table”的表上。master_table 總是存儲在數據庫的第一頁上。
了解更多關于SQLite的B樹的設計在這個文章。
/*
Open file connection to a page file name specified by zFileName with
nCache size cache
*/
int sqliteBtreeOpen(const char *zFilename, int mode, int nCache, Btree **ppBtree)
/*
Start transaction. This function should called before any btree modification
operations
*/
int sqliteBtreeBeginTrans(Btree *pBt)
/*
Insert key pKey with nKey byte and value pData with nData byte put
into the Btree
*/
int sqliteBtreeInsert(BtCursor *pCur, const void *pKey, int nKey,
const void *pData, int nData)
/*
Write data into the file
*/
int sqliteBtreeCommit(Btree *pBt)
/*
Move cursor to the matching pKey with nKey bytes
*/
int sqliteBtreeMoveto(BtCursor *pCur, const void *pKey, int nKey, int *pRes)
VDBE 是運行一組操作的虛擬機,由代碼生成器生成。包括插入、刪除、更新、選擇在內的所有 SQL 命令都轉換成一組操作碼,然后在虛擬機上運行。每個操作碼包含三個名為 p1、p2 和 p3 的輸入。您可以將此輸入視為函數的輸入。
下面我為以下 SQL 選擇語句添加了示例執行操作碼堆棧。PC 是程序計數器的指令 ID。 對我來說,SQLite 中最有趣的事情是我可以通過在 SQL 查詢的開頭附加“explain”關鍵字來查看給定 SQL 代碼的一組 VBDE 操作碼指令。
explain select * from foo;
個人電腦 | 操作碼 | P1 | P2 | P3 | 評論 |
1 | 列數 | 1 | 0 | 將列數設置為 1 | |
2 | 列名 | 0 | 0 | 價值 | 將列名設置為“值” |
3 | 打開 | 0 | 3 | 富 | 打開光標并將其指向第三頁,即 foo 表的根頁(p3 不重要 |
4 | 驗證Cookies | 46 | 0 | 確保架構未更改 | |
5 | 倒帶 | 0 | 11 | 將光標移動到第一個條目 | |
6 | 柱子 | 0 | 0 | 從 Btree 負載讀取數據并將其放入堆棧 | |
7 | 柱子 | 0 | 0 | ||
8 | ne | 1 | 10 | 從堆棧中彈出頂部的兩個元素。如果它們不相等,則跳轉到指令 P2。否則,繼續執行下一條指令。 | |
9 | 打回來 | 1 | 0 | 從堆棧中彈出 P1 值并將它們組成一個數組。這將是此 SQL 表達式的結果行 | |
10 | 下一個 | 0 | 5 | 將光標移動到下一條記錄,如果數據退出轉到 P2 否則轉到下一行 | |
11 | 關閉 | 0 | 0 | 關閉光標 |
Tokenizer、Parser 和 Code Generator 統稱為編譯器,可生成在 VBDE 上運行的操作碼集。Tokenizer 通過掃描 SQL 代碼生成一組令牌。然后,它驗證語法并生成解析樹。Lemon 解析器用于通過預定義的上下文無關語法來解析給定的 SQL 代碼。代碼生成器將這個解析樹轉換成一個用 SQLite 操作碼編寫的小程序。
以上是“SQLite數據庫的工作原理分析”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。