SQLite學習筆記(十一)&&Sqlite虛擬機原理

来源:http://www.cnblogs.com/cchust/archive/2016/01/20/5143425.html
-Advertisement-
Play Games

前言 我們知道任何一種關係型資料庫管理系統都支持SQL(Structured Query Language),相對於文件管理系統,用戶不用關心數據在資料庫內部如何存取,也不需要知道底層的存儲結構,熟悉SQL,就能熟練使用資料庫。SQL的引入,使得資料庫系統需要將SQL轉換為內部的數據結構,然後與.....


前言
      我們知道任何一種關係型資料庫管理系統都支持SQL(Structured Query Language),相對於文件管理系統,用戶不用關心數據在資料庫內部如何存取,也不需要知道底層的存儲結構,熟悉SQL,就能熟練使用資料庫。SQL的引入,使得資料庫系統需要將SQL轉換為內部的數據結構,然後與底層的存儲結構打通,達到用戶存取數據的目的。所謂的SQL對應的數據結構,我們通常稱之為執行計劃,每個SQL執行前,都需要生成執行計劃,然後執行。SQL如何變化到等價的執行計劃?我們熟悉的資料庫,Oracle,Sqlserver,Mysql等通過對SQL進行詞法分析,語法分析,語義分析,生成執行計劃等步驟,最終生成執行計劃,這個計劃一般是一個複雜的數據結構。SQLite也通過以上幾步生成執行計劃,但特別的是,SQLite的執行計劃是一串指令流,這個指令流是由代碼生成器生成,代碼生成器將語法樹翻譯成一種SQLite專用的內部指令,通過虛擬機來解析執行。指令流相當於SQL與虛擬機的中介,由於指令流是扁平的,SQLite提供方法(PRAGMA vdbe_trace=ON)讓用戶可以看到執行SQL的每一條指令,清楚地知道數據在SQLite內部是如何流轉的。本文主要講SQLite的虛擬機(Virtual Database Engine,簡稱VDBE)的原理以及相關的內部指令。

虛擬機
     所謂虛擬機是指對真實電腦資源環境的一個抽象,它為語言程式提供了一套完整的電腦介面。比如我們熟悉的JAVA語言,我們在跑JAVA程式時,其實是運行在JVM(JAVA Virtual Machine)環境中,所有的JAVA程式首先被編譯為.class類文件,這種類文件在虛擬機上執行,也就是說class文件並不與操作系統指令對應,而是經過虛擬機間接與操作系統交互。SQLite的虛擬機也是如此,編譯SQL產生的指令流只有SQLite虛擬機(Virtual Database Engine,簡稱VDBE)能識別,由虛擬機與底層的存儲(表,索引)交互,這種方式使得SQLite內部模塊分工非常清晰,耦合度很低。如下圖所示,我們可以看到VDBE的位置,它處於編譯器與Btree模塊的中間,是SQLite的核心,負責SQL到數據存取的交互。後面我提到的虛擬機都是指SQLite虛擬機(Virtual Machine,VM),VM模塊將底層存儲看作是記錄維度的文件系統,通過執行指令流,來讀寫表上的記錄。

                                      
VDBE數據結構和API

struct Vdbe{
sqlite3 *db;   /* The database connection that owns this statement */
Op *aOp;     /* Space to hold the virtual machine's program */
int nOp;     /* Number of instructions in the program */
Mem **apArg;    /* Arguments to currently executing user function */
Parse *pParse;  /* Parsing context used to create this Vdbe */
int pc;         /* The program counter */
Mem *aMem;      /* The memory locations */
int nMem;       /* Number of memory locations currently allocated */
Mem *aColName;  /* Column names to return */
u16 nResColumn; /* Number of columns in one row of the result set */
char *zSql;     /* Text of the SQL statement that generated this */
}

      我從源碼中選取了比較重要的對象,主要包括資料庫對象(db),指令流對象(aOp,nOp),綁定輸入的參數值(apArg),解析SQL的對象(pParse),指令流計數器(pc),存儲臨時變數的寄存器(aMem,nMem),返回結果集集的列名和列信息(aColName,nResColumn)以及執行的產生虛擬機指令的SQL(zSql)等。這些基本就是虛擬機對象的全部,有指令,有寄存器,有指令計數器,與彙編語言非常相似,只不過VDBE裡面的指令是sqlite內部識別的指令,而彙編語言指令是與機器指令對應的。如果想瞭解VDBE所有的對象,可以參考vdbeInt.h中關於該結構的定義,另外關於sqlite3結構和Parse結構可以參考sqliteInt.h文件。
     瞭解了Vdbe數據結構,我們再來看看我們平時常用的API是如何與VDBE交換數據的。通常我們要執行一個語句,會執行如下幾個步驟。
1.調用sqlite3_prepare_*來編譯生成指令流,返回一個sqlite3_stmt對象,其實這個對象就是vdbe對象。
2.調用sqlite3_bind_*來將參數傳遞給vdbe,
3.調用sqlite3_step進行執行,這時候會啟動虛擬機執行一條條指令,直到遇到中斷或者停止指令為止
4.調用sqlite3_column_*來獲取上一步準備好的結果集
5.調用sqlite3_finalize,銷毀vdbe對象,結束這次執行。
此外我們還可能用到sqlite3_reset介面,這個介面將指令流回退到第一條指令,用戶可以調用sqlite3_step重新執行。有關API的詳細說明,可以參考文件vdbeapi.c。 

虛擬機指令
      虛擬機核心就是扁平化指令,SQLite定義了一系列指令語言,每個指令做一小部分動作,虛擬機通過執行一些列指令達到查詢,修改資料庫的目的。每一條指令包含一個操作符和5個操作數,形式如下:<opcode,P1,P2,P3,P4,P5>。P1,P2,P3是一個32位有符號整數,P1一般是游標編號,P2一般是指令需要跳轉的指令位置,P4是一個32位/64位整數,64位的浮點數,或者是指向字元串的指針,或者是二進位等,P5是一個無編號的字元。不是每條指令都使用了全部5個操作數,有的指令只需要2到3個操作數。後面一篇文章我會結合實例詳細講解指令的作用,以及對應操作數的含義。

虛擬機執行流程
      虛擬機的核心流程在sqlite3VdbeExec函數中,我們調用sqlite3_step時就會調用到該函數。由於這個函數比較大,大概有6000行代碼,裡面包含了每條指令的執行過程,為了方便說明,我會簡化函數內容來說明這個函數的邏輯,抽象的代碼如下。從代碼流程來看,邏輯非常簡單,通過迴圈遍歷指令數組中的每條指令逐一執行,直到遇到中斷或終止指令為止。如果需要逐條瞭解每條指令的含義,還需要仔細閱讀代碼。

sqlite3VdbeExec(Vdbe *p)
{
  Op *aOp = p->aOp; /* Copy of p->aOp */
  Op *pOp = aOp; /* Current operation */

  for(pOp=&aOp[p->pc]; rc==SQLITE_OK; pOp++){
    switch(pOp->opcode){
    case OP_Goto: //jump to P2指向的指令
    {
      pOp = &aOp[pOp->p2 - 1];
      break;
    }
    case OP_Integer: // value P1 is written into register P2.
    {
      pOut = out2Prerelease(p, pOp);
      pOut->u.i = pOp->p1;
      break;
    }
    case OP_Real:
    {
      ......
      break;
    }
    case OP_Halt:
    {
      ......
      break;
    }
    ... 
   }// end of switch
  } // end of for
}

小結
     本文介紹了SQLite虛擬機以及對應的指令流。通過介紹vdbe的存儲結構,我們瞭解到vdbe對象所包含的內容;通過介紹API,我們瞭解到API與虛擬機的關係;通過介紹函數sqlite3VdbeExec的實現,我們知道虛擬機執行流程非常清晰,通過執行一系列指令流,就可以實現查詢,更新數據。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 主要用於UITableView和UICollectionView,也可以用於UIScrollView,其實主要是前兩個會用到空白或者網路出錯頁 採用給UIScrollView添加代理方法來給頁面添加空白頁,源碼很有學習意義
  • 文章內容大綱1、NSMutableAttributedString的基本使用2、NSMutableAttributedString的簡易封裝3、使用開源代碼GOBMarkupPaser處理富文本4、UITextKit簡介5、編程思想的相關思考前言富文本使用案例:這裡我自己也用了富文本實現了簡單的卻也...
  • 一、沙盒(SandBox) 1.沙盒機制 1> 每個應用都有屬於自己的存儲空間,即沙盒。 2> 應用只能訪問自己的沙盒,不可訪問其他區域。 3> 如果應用需要進行文件操作,則必須將文件存放在沙盒中,尤其是資料庫文件,在電腦上操作時,可以去訪問,但是如果要裝在真機上可以使用,必須將資料庫文件...
  • 最近有學生做畢業設計,想使用懸浮窗這種效果,其實很簡單,我們可以通過系統服務WindowManager來實現此功能,本章我們來試驗一下在當前Activity之上創建一個懸浮的view。第一步:認識WindowManagerl 這個介面用於與 window manager (視窗管理器, 應用框架.....
  • 使用Microsoft SQL SERVER 2014 Management Studio訪問Azure SQL Database時,查看存儲過程時遇到下麵錯誤信息: TITLE: Microsoft SQL Server Management Studio --------------------...
  • 在SQL標準中定義了四種隔離級別,每一種級別都規定了一個事務中所做的修改,哪些是在事務內和事務間可見的,哪些是不可見的。較低級別的隔離通常可以執行更高的併發,系統的開銷也更低。1、未提交讀(Read uncommitted)在未提交讀級別,事務中的修改,即使沒有提交,對其他事務也都是可見的。事務可以...
  • 功能說明:備份和恢復SQL Server資料庫* 作者: 劉功勛;* 版本:V0.1(C#2.0);時間:2007-1-1* 當使用SQL Server時,請引用 COM組件中的,SQLDMO.dll組件* 當使用Access中,請瀏覽添加引用以下兩個dll* 引用C:/Program Files/...
  • 標簽:utf8概述本篇文章介紹mycat怎樣在分庫分表的情況下保證主鍵的全局唯一方法,接下來就來分析三種方法各自的優缺點。配置文件方式獲取1.修改server配置文件vim server.xml0註:sequnceHandlerType 配置為0表示使用本地文件讀取。2.配置sequence_con...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...