Rocksdb引擎記錄格式

来源:http://www.cnblogs.com/cchust/archive/2016/10/17/5965646.html
-Advertisement-
Play Games

Rocksdb是一個kv引擎,由facebook團隊基於levelDB改進而來,Rocksdb採用LSM-tree存儲數據,良好的讀寫特性以及壓縮特性使得其非常受歡迎。此外,Rocksdb引擎作為插件已經集成在facebook維護的MySQL分支,用戶可以通過SQL來訪問rocksDB。本文主要通過 ...


     Rocksdb是一個kv引擎,由facebook團隊基於levelDB改進而來,Rocksdb採用LSM-tree存儲數據,良好的讀寫特性以及壓縮特性使得其非常受歡迎。此外,Rocksdb引擎作為插件已經集成在facebook維護的MySQL分支,用戶可以通過SQL來訪問rocksDB。本文主要通過分析Rocksdb引擎的記錄格式,並通過對比innodb,來讓大家瞭解Rocksdb。Rocksdb作為一個kv引擎,用戶通過put(key,value)來寫入key,或者通過get(key)介面來獲取value,對rocksdb本身而言,每條記錄都是一個key-value。當Rocksdb作為一個存儲引擎接入到MySQL時,key-value結構如何存儲表中各個索引,以及如何記錄中各個列的信息是本文要具體討論的。rocksdb引擎與innodb引擎類似,也是採用索引組織表,無論是表(主鍵索引)還是二級索引都是以LSM tree方式組織,rocksdb記錄主要包括三部分,key,value和meta三部分內容,具體見下表,然後我通過介紹一條具體記錄在rocksdb引擎中的存儲格式來說明問題。

rocksdb基本記錄存儲格式

key_size

key

value_size

value

PK/SecKey

Columns data

SeqenceId,flag 

create table row_format(  
id int not null,  
c1 int,  
c2 char(10) not null,  
c3 char(10),  
c4 varchar(10),  
c5 varchar(10) not null,  
c6 blob,  
c7 binary(10) not null,  
c8 varbinary(10)) engine=rocksdb;
insert into row_format(id,c2,c4,c5,c7) values(1,'abc','abc','efg','111')

 key部分:

Index_id

key

4bytes

8bytes

0x7fdfa4278ea0: 0x00    0x00    0x01    0x7b    0x00    0x00    0x00    0x00

0x7fdfa4278ea8: 0x00    0x00    0x00    0x05

Index_id:索引的編號,全局唯一。

rowid:由於表沒有主鍵,系統會產生一個bigint類型的rowid作為主鍵,占用8個位元組,而innodb引擎的rowid占6個位元組,需要註意的是rowid存儲採用的大端的存儲(高位存儲低位元組),這裡主要是為了memcompare。

Value部分:

 

Null-flag

ID

C1

C2

C3

C4

C5

C6

C7

C8

Length

1B

4B

----

30B

----

4B

4B

----

10B

----

Value

 

1

 

abc0x20…

 

len+value

len+value

 

1110x00…

 

0x7fdfa4251e50: 0x1b    0x01    0x00    0x00    0x00    0x61    0x62    0x63

0x7fdfa4251e58: 0x20    0x20    0x20    0x20    0x20    0x20    0x20    0x20

0x7fdfa4251e60: 0x20    0x20    0x20    0x20    0x20    0x20    0x20    0x20

0x7fdfa4251e68: 0x20    0x20    0x20    0x20    0x20    0x20    0x20    0x20

0x7fdfa4251e70: 0x20    0x20    0x20    0x03    0x61    0x62    0x63    0x03

0x7fdfa4251e78: 0x65    0x66    0x67    0x31    0x31    0x31    0x00    0x00

0x7fdfa4251e80: 0x00    0x00    0x00    0x00    0x00

說明:

  1. Value的最前面部分(0x1b)就是存放記錄的null信息。根據記錄中可以為null欄位的個數,確認需要占用的位元組數,如果小於8個,則只需要一個位元組。例子中,c1,c3,c4,c6,c8均可以為null,因此需要5個bit,所以用1個byte表示Null-flag即可,由於插入記錄中,c4不為null,則對應的bit為0,也就是0x00011011。
  2. 對於null,無論是定長還是非定長數據類型,都不占用真實的存儲空間,只需要一個bit位來表示為null即可。
  3. 空串’’與null,上面提到了null需要占一個標記位,而對於’’,如果是變長欄位仍然需要存儲長度信息,對於定長欄位,則會補全。
  4. 對於變長欄位,比如varchar,0x03 0x61 0x62 0x63數據有len+data組成,如果數據長度小於256,len只需要占用一個byte;如果len大於255,且小於65536,則需要占用2個位元組,對於longblob類型,則需要占4個位元組。
  5. 對於定長欄位,不需要存長度信息直接存儲data,如果不足則補充。補充字元有點詫異,對於char類型,補充0x20,對於binary類型,補充0x00。
  6. 對於lob類型,比如tinyblob,blob,mediumblob,longblob,以及對應的text類型,處理策略與varchar類似,存儲長度的位元組數根據數據類型的範圍確定,比如blob長度占用2個位元組,而longblob的長度占4個位元組。所以在rocksdb裡面,沒有innodb中所謂“溢出頁”的概念。對於innodb引擎,如果blob欄位內容超過768位元組,多餘的data存儲在溢出頁,頁內通過20個位元組指向溢出頁,主要包括第一個blob頁的space_id,page_no和起始偏移,如果存在多個blob頁,則頁與頁之間通過類似的方式進行關聯。具體可以參考btr0cur.h文件中關於BTR_EXTERN_xxx相關的巨集定義,以及介面btr_copy_externally_stored_field_prefix_low。
  7. 有關value部分的存儲實現可以參考rocksdb引擎介面convert_record_to_storage_format,convert_record_from_storage_format和innodb引擎介面row_mysql_store_col_in_innobase_format,row_sel_field_store_in_mysql_format。

Meta部分:

Meta部分主要是SequenceID,這個SequenceID在事務提交時產生,主要用於rocksDB實現MVCC,用於可見性判斷,此外Meta中還包含flag信息,由於標示記錄類型,put,delete,singleDelete等,具體而言Sequence占7個位元組,flag占1個位元組。

rocksdb索引格式

      Rocksdb中,所有的數據都是通過索引來組織,與Innodb類似,也是索引組織表,每個索引有一個全局唯一的index_id。索引主要包括兩類:主鍵索引和二級索引,前面介紹的記錄格式,也就是主鍵索引的格式,包括key,value和meta三部分。二級索引也包含key,value和meta三部分,但是value中不包含任何數據,只是包含checksum信息。

主鍵索引

key

Value

Meta

Index_id

PK

NULL標記位

列數據

Checksum(可選)

SeqId,flag

二級索引

key

Value

Meta

Index_id

SecondaryKey

PK

Checksum(可選)

SeqId,flag

對比innodb引擎(innodb_file_format=Barracuda,row_format=compact)

innodb記錄格式

變長欄位長度列表

NULL標記位

record_header

Trxid

Roll_ptr

列數據

create table row_format(  
id int not null,  
c1 int,  
c2 char(10) not null,  
c3 char(10),  
c4 varchar(10),  
c5 varchar(10) not null,  
c6 blob,  
c7 binary(10) not null,  
c8 varbinary(10)) engine=innodb;
insert into row_format(id,c2,c4,c5,c7) values(1,'1234','ab','efg','111');

記錄內容:

0000c0b0  00 00 03 02 0a 1b 00 00  18 ff b5 00 00 00 00 28  |...............(|

0000c0c0  00 00 00 00 01 01 03 83  00 00 01 36 01 10 80 00  |...........6....|

0000c0d0  00 01 31 32 33 34 20 20  20 20 20 20 61 62 65 66  |..1234      abef|

0000c0e0  67 31 31 31 00 00 00 00  00 00 00 00 00 00 00 00  |g111............|

說明:

     1.   03 02 0a這裡存的是長度信息,所有非null的變長列信息都逆序存在一起,這裡按先後順序是c5,c4,c2,這裡innodb將char(10)也當作變長欄位處理了。

     2.  1b存儲的是null信息,與rocksdb對null處理一致。00 00  18 ff b5存儲的是record-header。

     3. 00 00 00 00 28 00 00 00 00 01 01 03 83  00 00 01 36 01 10, 這三部分別是rowid,trxid和roll_ptr,分別占6個位元組,6個位元組和7個位元組。

     4. 最後一部分是數據,null不占任何存儲空間,與rocksdb處理類似。區別在於對於char類型的處理,innodb將欄位c2類型char(10)補齊到10個位元組,存儲為31 32 33 34 20 20 20 20 20 20,將其作為varchar處理,記錄了長度信息;而Rocksdb則是補齊到30個位元組(utf8字元集),作為char處理,不記錄長度信息。

      整體而言,innodb記錄格式包含了record_header(記錄頭信息),占5個位元組,主要包括記錄號(heap_no),列數目,下一條記錄的位置以及是否刪除等信息。rocksdb則相對簡單,只有整體的value-size,以及通過Meta中flag標示記錄的狀態put 或者是delete。innodb將變長列長度信息集中存放在一起,使得查找任意列的代價都差不多,而rocksdb的變長列信息則是放在每列的前面,訪問最後一列需要逐一計算前面的列,才能定位。此外,由於innodb引擎與rocksdb引擎由於實現MVCC的機制不同,導致innodb引擎和rocksdb引擎需要存儲的額外信息也不同。Innodb實現MVCC依賴於回滾段信息,記錄需要額外存儲trxid和roll_ptr兩個欄位,分別是6個位元組和7個位元組(type,rsegid,pageNO,offset),其中type占一個bit位,標示insert 或者是update類型,rsegid回滾段id占7bit位,pageNo占4個位元組,頁內偏移占2個位元組。Rocksdb實現MVCC則是依賴於SequenceID,通過SequenceID來判斷記錄的可見性,SequenceID占7個位元組。

      細節上來說,RocksDB引擎和innodb引擎在處理null,char和varchar的方式類似,但innodb對於char類型做了優化,統一作為varchar處理。另外rocksdb引擎沒有對blob做特殊處理。你可能會有疑問,rocksdb不是也有block_size嗎,如果設置為16k,blob數據超過16k怎麼辦?對於innodb而言,由於表實質是以一個個page通過B-tree組織起來的,每個page是固定大小,當記錄非常大時,就需要藉助溢出頁,通過鏈接的方式關聯起來。而rocksdb中block_size只是一個壓縮單位,並沒有嚴格約束,文件內容以block組織,由於文件中block可能是壓縮過的,因此每個block的大小不固定,通過偏移來定位具體某個block的位置。如果遇到大的blob數據,則可能這個block比較大,記錄所有數據存儲在一起,不會跨block。

      對於索引長度限制也有所不同,對於innodb引擎來說,索引中單列長度不能超過767個位元組,而rocksdb引擎單列長度不超過2048個位元組,具體可以參考max_supported_key_part_length各自的實現;整個索引的長度,rocksdb和innodb都限制在3072個位元組,實際上是server層的限制,因為它們的各自限制的長度都比server層的大。具體可以參考各自max_supported_key_length的實現。

參考文檔

http://dev.mysql.com/doc/refman/5.7/en/innodb-physical-record.html

http://hedengcheng.com/?p=127

http://www.cnblogs.com/zhoujinyi/articles/2726462.html

 


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

-Advertisement-
Play Games
更多相關文章
  • service常見的有2種方式,本地service以及remote service。 這2種的生命周期,同activity的通信方式等,都不相同。 關於這2種service如何使用,這裡不做介紹,只是介紹一些被遺漏的地方 1.遠程Service(AIDL方式) package com.joyfulm ...
  • 1.隱藏顯示dock的快捷鍵cmd - opt - d 2.如何快速調出命令終端或者調出其他程式通過安裝 Alfred,Alfred算是神兵利器——Alfred 3.Dock在隱藏後,滑鼠移過去,Dock顯示出來時,稍微有延遲的感覺可以通過下麵的終端命令進行調整: defaults write co ...
  • 一個簡單的關於頁面,有一個圖片,版本號,App名稱等,著重演示各個系列的文章完整集成示例. ...
  • Linux文件和目錄許可權解讀 如何設置Linxu文件和目錄的許可權 字元表示法 1)ls -l:查看所在目錄所有文件的許可權 2)chmod u=r file:把file文件的當前(用戶user)的許可權賦值為可寫模式 3)chmod g=wrx file:把file文件的當前(組gruop)的許可權賦值為 ...
  • 在IOS開法中經常會遇到鍵盤遮擋屏幕的事情(比如輸入賬號密碼驗證碼等等),就使得原本都不大的屏幕直接占了一半甚至更多的位置,這倒無所謂,關鍵是擋住了下麵的按鈕。這樣的話按鈕的事件也就觸發不了,最好的解決辦法就是當輸入這些信息的時候讓整個屏幕上移一個鍵盤的位置,或者上移到指定的位置。 首先一般輸入的話 ...
  • 首先吹一下意圖:切割字元串是因為在資料庫中存圖片地址時,可能一件商品對應有多張圖片。那麼我們可以建一個商品表(goods)和一個圖片表(goods_image),然後讓圖片表的id作為商品表的外鍵,實現一對多的關聯。 但是想到建表一個路徑一個路徑的存,數據也蠻多的,然後既然可以在商品表中添加一個欄位 ...
  • 控制台列印的信息如下 解決辦法: Xcode8裡邊 Edit Scheme... -> Run -> Arguments, 在Environment Variables裡邊添加 OS_ACTIVITY_MODE = disable 步驟1. 步驟2. 步驟3. 結束設置 ...
  • 調整圖片大小的時候按下:option鍵讓讓控制項跟內容一樣大:command+= http://www.cr173.com/html/21801_1.html 一、關於運行調試1、運行,停止,都在工具欄的Product里。Command + R 運行。Command + . 停止 2、F6單步調試、F ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...