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
更多相關文章
  • 上篇文章簡單討論了虛擬機的原理,這篇文章我們詳細討論下指令,具體從幾種典型的SQL語句來看看每種SQL對應的指令流,以及每個指令的含義。通過explain語句,可以看到語句對應的指令流;通過pragma vdbe_trace=on指令,我們甚至可以得到語句對應的指令執行流程,包括跳轉等。測試表結.....
  • 作為一個DBA,排除SQL Server問題是我們的職責之一,每個月都有很多人給我們帶來各種不能解釋卻要解決的性能問題。我就多次聽到,以前的SQL Server的性能問題都還好且在正常範圍內,但現在一切已經改變,SQL Server開始糟糕, 瘋狂的事情不能解釋。在這個情況下我介入,分析下整個SQL...
  • 在 SQL 跟蹤中,如果事件是在跟蹤定義中列出的事件類的實例,則收集這些事件。可以將這些事件從跟蹤中篩選出來或為其目標進行排隊。目標可以是文件或 SQL Server 管理對象 (SMO),它可以使用管理 SQL Server 的應用程式中的跟蹤信息。SQL 跟蹤的優點 Microsoft S...
  • Oracle創建用戶、表空間、導入導出、...命令//創建臨時表空間create temporary tablespace ext_temptempfile 'D:\oracle\product\10.2.0\oradata\test\ext_temp.dbf'size 32mautoextend ...
  • 1.sql_safe_updates官方解釋如下:If set to 1, MySQL aborts UPDATE or DELETE statements that do not use a key in the WHERE clause or a LIMIT clause. (Specifica...
  • 今天,啟動MySQL伺服器失敗,如下所示:[root@spark01 ~]# /etc/init.d/mysqld startStarting mysqld (via systemctl): Job for mysqld.service failed because the control pro....
  • use mysql;ALTER TABLE `proc`MODIFY COLUMN `comment` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL AFTER `sql_mode`;具體原因請看:http://www.cnblogs.com/....
  • 主要參考了博文:宋沄劍 -理解SQL SERVER中的邏輯讀,預讀和物理讀 和 宋沄劍 - T-SQL查詢進階--理解SQL Server中索引的概念,原理以及其他,以下內容為對其博文的讀書筆記。 1. 資料庫的數據存儲形式 在談到幾種不同的讀取方式之前,首先要理解SQL SERVER數據存儲的方式...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...