OceanBase 4.3 特性解析:列存技術

在涉及大規模數據的復雜分析或即時查詢時,列式存儲是支撐業務負載的關鍵技術之一。相較于傳統的行式存儲,列式存儲采用了不同的數據文件組織方式,它將表中的數據以列為單位進行物理排列。這種存儲模式允許在分析過程中,查詢計算僅需針對所需的列數據進行掃描,從而避免了不必要的整行掃描,顯著降低了IO和內存等資源的消耗,進而提升了計算效率。此外,列式存儲天然具備更佳的數據壓縮優勢,能夠實現較高的壓縮比,有效節約了存儲空間,并降低了網絡傳輸帶寬的占用。

常見的列存存儲引擎在實現上往往假設不會有大量隨機更新, 盡量保證列存組織數據是靜態的。當真正伴隨大量數據隨機更新時,也會不可避免的存在系統性能問題。OceanBase LSM-Tree 架構可以將基線數據和增量數據分別處理,正好可以解決這一場景問題。因此 OceanBase 4.3 版本基于當前架構基礎進行擴展,正式推出列存引擎,在一個架構、一個數據庫上,實現了列存和行存數據存儲一體化,兼顧 TP 和 AP 查詢性能。

為了讓有分析訴求的用戶順暢使用新版本,圍繞列存引擎,從優化器到執行器、從 DDL 到事務處理等多模塊都進行了適配優化。包括基于列存的新的代價模型和向量化引擎,查詢下壓功能的擴展和增強,Skip Index,新的列式編碼算法,自適應 Compaction 等。本文將深入探討 OceanBase 4.3 版本帶來的列存能力、應用場景,以及用戶關心的未來發展規劃

一、列存整體架構

OceanBase 作為原生分布式數據庫,默認情況下會為用戶數據創建多個副本。為了充分利用多副本的優勢,為用戶提供數據強校驗和數據遷移重用等增強體驗,OceanBase 自研的 LSM-Tree 存儲引擎做了深度優化:

○ ?基線數據:相較于業內常見的 LSM-Tree 實現邏輯,OceanBase 提出了"每日合并"的概念。用戶可定期或根據操作選擇一個全局版本號,所有副本的租戶數據將在這個版本上進行一輪 Major Compaction,生成這個版本的基線數據。所有副本在同一版本下的基線數據完全一致,物理上保持一致。

○ ?增量數據:相對于基線數據,增量數據是指在最新版本的基線數據之后寫入的數據。增量數據可以是剛寫入Memtable的內存數據,也可以是已經轉儲為SSTable 的磁盤數據。增量數據在每個副本中獨立維護,不保證一致性,并且包含了所有多版本的數據。

基于列存應用場景隨機更新量可控的背景,OceanBase 4.3 結合自身基線數據和增量數據的特質,提出了一套對上層透明的列存實現方式:基線數據存儲為列存模式,增量數據保持行存,確保用戶所有 DML 操作不受影響,上下游同步無縫接入,列存表數據仍然可以像行存表一樣進行所有事務操作。列存模式下每列數據存儲為一個獨立 SSTable,所有列的 SSTable 組合成為一個虛擬 SSTable 作為用戶的列存基線數據。同時,用戶可根據實際業務訴求在建表環節指定設置,基線數據可以支持行存、列存、行存列存冗余三種模式,提供更好的靈活性。

1716796000

OceanBase 4.3 版本中不僅在存儲引擎中實現了列存模式,更從優化器、執行器以等多維度進行列存的適配優化。用戶在遷移到列存模式后基本上不會感受到業務變化,能夠像使用行存一樣享受到列存帶來的性能優勢。列存引擎的全面優化,也使得 OceanBase 真正實現了 TP & AP 一體化,實現了一套引擎、一套代碼支持不同類型業務的目標,打造更加完善的 HTAP 混合負載實時分析能力。

二、OceanBase 實現列存,有哪些天然優勢

(一)成熟的 LSM-Tree 引擎

與傳統數據庫相比,OceanBase 擁有天然的 Delta Store,非常適合實現列存。基于 LSM-Tree 存儲引擎的支持,OceanBase 列存不僅支持完整的事務,而且基礎算子的性能不弱于傳統的 TP 數據庫。在列存上,完整的事務支持使得 OceanBase 在更新方面具有天然優勢,所有事物語義和多樣事物的管理對用戶來說完全透明的,用戶可以輕松切換到列存模式,將列存數據庫當成行存數據庫使用,對業務完全透明,不需要做任何改動。

(二)完善的執行引擎

OceanBase 不僅擁有完整的執行引擎,還具備通用的優化器是通用的。在行存模式下,OceanBase 已經實現向量化存儲引擎的無縫對接,無需任何修改即可支持向量化執行。此外,OceanBase 實現一套優化器的代碼在上層對行存和列存進行不同代價的估算,使得用戶的 SQL 可以自動選擇行存或列存。

(三)靈活的原生分布式

OceanBase 天然支持分布式并行查詢引擎,未來還可以輕松擴展到列存異構副本。列存異構副本的優勢體現在用戶需要完全硬隔離的應用場景中,未來的OceanBase 版本將新增這一功能。

綜上所述,OceanBase 憑借其天然優勢推動了 4.3 版本中列存功能的實現。引入列存儲引擎后,OceanBase 整體架構在外部表現上完全不變,并且從架構層面支持了列存相關的三種模式:

○ ?基線列存 +增量行存:基線數據采用列存方式存儲,增量數據采用行存方式存儲。

○ ?靈活的行存/列存索引:可以對行存表建立列存索引,也可以對列存表建立行存索引,還可以對兩者進行任意組合。由于所有列存表和索引的底層存儲結構是統一的,因此 OceanBase 可以自動支持列存和行存的索引。

○ ?列存副本:OceanBase 正在研發的列存副本功能。得益于原生分布式能力,只需對模式或表做部分修改,即可以通過 Compaction 將新增的只讀副本轉換為列存存儲模式。

三、列存使用方法

(一)默認創建列存表

對于 OLAP 業務需求,我們推薦默認創建列存表。如何確保租戶創建出來的表默認為列存表?只通過下面的配置項即可實現:

alter system set default_table_store_format = "column";

隨后我們創建的表格沒有指定 column group 時,默認創建為列存表。

OceanBase(root@test)>create table  t1 (c1 int primary key, c2 int ,c3 int);
Query OK,0 rows affected (0.301 sec)OceanBase(root@test)>show create table t1;CREATE TABLE `t1` (`c1` int(11) NOT NULL,`c2` int(11) DEFAULT NULL,`c3` int(11) DEFAULT NULL,PRIMARY KEY (`c1`)
) DEFAULT CHARSET = utf8mb4 ROW_FORMAT = DYNAMIC COMPRESSION = 'zstd_1.3.8' REPLICA_NUM = 1 BLOCK_SIZE = 16384 USE_BLOOM_FILTER = FALSE TABLET_SIZE = 134217728 PCTFREE = 0
WITH COLUMN GROUP(each column)1 row in set (0.101 sec)

(二)指定創建列存表

為了方便用戶創建列存表,列存引入新的語法 with column group,當用戶建表時最后指定 `with column group(each column)` ,即表示創建列存表。

OceanBase(root@test)>create table  tt_column_store (c1 int primary key, c2 int ,c3 int) with column group (each column);
Query OK,0 rows affected (0.308 sec)OceanBase(root@test)>show create table tt_column_store;CREATE TABLE `tt_column_store` (`c1` int(11) NOT NULL,`c2` int(11) DEFAULT NULL,`c3` int(11) DEFAULT NULL,PRIMARY KEY (`c1`)
) DEFAULT CHARSET = utf8mb4 ROW_FORMAT = DYNAMIC COMPRESSION = 'zstd_1.3.8' REPLICA_NUM = 1 BLOCK_SIZE = 16384 USE_BLOOM_FILTER = FALSE TABLET_SIZE = 134217728 PCTFREE = 0 WITH COLUMN GROUP(each column)1 row in set (0.108 sec)

(三)指定創建列存行存冗余表

在某些場景下,用戶可以容忍一定程度的數據冗余,以滿足 AP/TP 業務場景的雙重需求。此時,可以增加行存數據的冗余,通過 `with column group` 語法增加指定 `all columns` 即可實現。

create table  tt_column_row (c1 int primary key, c2 int , c3 int) with column group (all columns, each column);
Query OK, 0 rows affected (0.252 sec)OceanBase(root@test)>show create table tt_column_row;
CREATE TABLE `tt_column_row` (`c1` int(11) NOT NULL, `c2` int(11) DEFAULT NULL, `c3` int(11) DEFAULT NULL, PRIMARY KEY (`c1`)
) DEFAULT CHARSET = utf8mb4 ROW_FORMAT = DYNAMIC COMPRESSION = 'zstd_1.3.8' REPLICA_NUM = 1 BLOCK_SIZE = 16384 USE_BLOOM_FILTER = FALSE TABLET_SIZE = 134217728 PCTFREE = 0 WITH COLUMN GROUP(all columns, each column)1 row in set (0.075 sec)

(四)列存掃描

如何查看是否列存掃描計劃?計劃展示上新增 COLUMN TABLE FULL SCAN,描述列存表的范圍掃描。

OceanBase(root@test)>explain select * from tt_column_store;
+--------------------------------------------------------------------------------------------------------+
| Query Plan                                                                                             |
+--------------------------------------------------------------------------------------------------------+
| =================================================================                                      |
| |ID|OPERATOR              |NAME           |EST.ROWS|EST.TIME(us)|                                      |
| -----------------------------------------------------------------                                      |
| |0 |COLUMN TABLE FULL SCAN|tt_column_store|1       |7           |                                      |
| =================================================================                                      |
| Outputs & filters:                                                                                     |
| -------------------------------------                                                                  |
|   0 - output([tt_column_store.c1], [tt_column_store.c2], [tt_column_store.c3]), filter(nil), rowset=16 |
|       access([tt_column_store.c1], [tt_column_store.c2], [tt_column_store.c3]), partitions(p0)         |
|       is_index_back=false, is_glOceanBaseal_index=false,                                                      |
|       range_key([tt_column_store.c1]), range(MIN ; MAX)always true                                     |
+--------------------------------------------------------------------------------------------------------+

計劃展示上新增 COLUMN TABLE GET,描述列存表上的指定主鍵的 get 操作。

OceanBase(root@test)>explain select * from tt_column_store where c1 = 1;
+--------------------------------------------------------------------------------------------------------+
| Query Plan                                                                                             |
+--------------------------------------------------------------------------------------------------------+
| ===========================================================                                            |
| |ID|OPERATOR        |NAME           |EST.ROWS|EST.TIME(us)|                                            |
| -----------------------------------------------------------                                            |
| |0 |COLUMN TABLE GET|tt_column_store|1       |14          |                                            |
| ===========================================================                                            |
| Outputs & filters:                                                                                     |
| -------------------------------------                                                                  |
|   0 - output([tt_column_store.c1], [tt_column_store.c2], [tt_column_store.c3]), filter(nil), rowset=16 |
|       access([tt_column_store.c1], [tt_column_store.c2], [tt_column_store.c3]), partitions(p0)         |
|       is_index_back=false, is_global_index=false,                                                      |
|       range_key([tt_column_store.c1]), range[1 ; 1],                                                   |
|       range_cond([tt_column_store.c1 = 1])                                                             |
+--------------------------------------------------------------------------------------------------------+
12 rows in set (0.051 sec)

如何通過 Hint 指定列存行存冗余表走列存掃描?對于列存行存冗余表,優化器會根據代價選擇走行存或者列存掃描,如簡單場景做全表掃描,會默認使用行存生成計劃。

OceanBase(root@test)>explain select * from tt_column_row;
+--------------------------------------------------------------------------------------------------+
| Query Plan                                                                                       |
+--------------------------------------------------------------------------------------------------+
| ========================================================                                         |
| |ID|OPERATOR       |NAME         |EST.ROWS|EST.TIME(us)|                                         |
| --------------------------------------------------------                                         |
| |0 |TABLE FULL SCAN|tt_column_row|1       |3           |                                         |
| ========================================================                                         |
| Outputs & filters:                                                                               |
| -------------------------------------                                                            |
|   0 - output([tt_column_row.c1], [tt_column_row.c2], [tt_column_row.c3]), filter(nil), rowset=16 |
|       access([tt_column_row.c1], [tt_column_row.c2], [tt_column_row.c3]), partitions(p0)         |
|       is_index_back=false, is_global_index=false,                                                |
|       range_key([tt_column_row.c1]), range(MIN ; MAX)always true                                 |
+--------------------------------------------------------------------------------------------------+

如果用戶希望通過手動調優走列存掃描,可以通過 hint USE_COLUMN_TABLE 來強制 tt_column_row 表走列存掃描。

OceanBase(root@test)>explain select /*+ USE_COLUMN_TABLE(tt_column_row) */ * from tt_column_row;
+--------------------------------------------------------------------------------------------------+
| Query Plan                                                                                       |
+--------------------------------------------------------------------------------------------------+
| ===============================================================                                  |
| |ID|OPERATOR              |NAME         |EST.ROWS|EST.TIME(us)|                                  |
| ---------------------------------------------------------------                                  |
| |0 |COLUMN TABLE FULL SCAN|tt_column_row|1       |7           |                                  |
| ===============================================================                                  |
| Outputs & filters:                                                                               |
| -------------------------------------                                                            |
|   0 - output([tt_column_row.c1], [tt_column_row.c2], [tt_column_row.c3]), filter(nil), rowset=16 |
|       access([tt_column_row.c1], [tt_column_row.c2], [tt_column_row.c3]), partitions(p0)         |
|       is_index_back=false, is_global_index=false,                                                |
|       range_key([tt_column_row.c1]), range(MIN ; MAX)always true                                 |
+--------------------------------------------------------------------------------------------------+

類似的方式,通過 Hint NO_USE_COLUMN_TABLE 可以強制表不進行列存掃描。

OceanBase(root@test)>explain select  /*+ NO_USE_COLUMN_TABLE(tt_column_row) */ c2 from tt_column_row;
+------------------------------------------------------------------+
| Query Plan                                                       |
+------------------------------------------------------------------+
| ========================================================         |
| |ID|OPERATOR       |NAME         |EST.ROWS|EST.TIME(us)|         |
| --------------------------------------------------------         |
| |0 |TABLE FULL SCAN|tt_column_row|1       |3           |         |
| ========================================================         |
| Outputs & filters:                                               |
| -------------------------------------                            |
|   0 - output([tt_column_row.c2]), filter(nil), rowset=16         |
|       access([tt_column_row.c2]), partitions(p0)                 |
|       is_index_back=false, is_global_index=false,                |
|       range_key([tt_column_row.c1]), range(MIN ; MAX)always true |
+------------------------------------------------------------------+
11 rows in set (0.053 sec)

四、未來展望

OceanBase 4.3 列存的引入,為用戶的數據分析以及實時分析場景提供了新的選擇。未來,OceanBase 列存將持續演進,為用戶帶來更加豐富的 feature、更強勁的性能以及更靈活的部署模式。

第一,更豐富的功能。目前,我們支持純列存儲引擎,未來將實現可自定義的靈活列組組織支持,滿足不同場景的分析需求。此外,我們計劃將增量旁路導入功能進一步增強,幫助用戶實現高效的數據導入,縮短數據分析準備時間。

第二,更好的性能。增強 Skip Index 的支持,使其能夠更好地滿足用戶的查詢需求。此外,我們計劃實現格式一體化,目前存儲的格式多樣化,未來將實現存儲格式與 SQL 向量化引擎的緊密結合,使得在執行 SQL 計算時,系統能夠識別不同的存儲格式,從而幫助用戶節省更多的數據轉換開銷。

第三,更靈活的部署模式。在未來的版本中,我們將支持 OLAP 所需的異構副本,以滿足用戶對強依賴異構副本的需求。此外,未來還將支持存算分離模式,使得所有用戶的 AP 數據庫都能夠以更低的成本享受存儲與計算的分離。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/22254.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/22254.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/22254.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

flowable工作流 完成任務代碼 及擴展節點審核人(實現多級部門主管 審核等)詳解【JAVA+springboot】

低代碼項目 使用flowable 工作流 完成任務代碼 詳解 可以看到 complete()方法 傳遞了流程變量參數var 前端傳遞此參數就可以實現 流程中 審批 更新流程變量參數var 也可以進行更多擴展 實現流程中更新表單內容功能 啟動流程實例代碼 實現對于流程自定義 動態節點審核人 功…

中央空調節能的分戶計費系統

中央空調節能 在建筑能耗中,中央空調能耗一般占到了40%---60%的比例,因此如何有效降低空調能耗就成為建筑節能的重中之重。 項目案例描述 山東銀座購物廣場:為集購物中心、高級酒店式公寓和辦公為一體的綜合性公共建筑。整體建筑共為地下3層&…

副業變現:Midjourney繪畫賺錢的6種方式

今年被稱為AI元年,其中最火的兩款AI工具非ChatGpt和Midjourney莫屬。究其原因,無非兩點:第一,它提高了生產力,之前需要兩年完成的工作,使用ChatGpt兩天就完成。 第二,它帶來了副業收入&#x…

JavaScript異步編程簡單介紹

JavaScript異步編程是一種編程模式,用于處理需要等待某些操作完成之后才能繼續執行的代碼。這些操作可以是網絡請求、文件讀取、定時器等等。 異步編程的目標是避免阻塞代碼執行,在等待操作完成的同時,允許其他代碼繼續執行。 以下是一個使…

Springboot-RabbitMQ 消息隊列使用

一、概念介紹: RabbitMQ中幾個重要的概念介紹: Channels:信道,多路復用連接中的一條獨立的雙向數據流通道。信道是建立在真實的 TCP 連接內地虛擬連接,AMQP 命令都是通過信道發出去的,不管是發布消息、訂閱…

2021 hnust 湖科大 數字系統設計與VHDL課程 大作業 - 出租車計價器設計

2021 hnust 湖科大 數字系統設計與VHDL課程大作業-出租車計價器設計 描述 大二上的eda考查課的實驗,額外實現了停車等待2分鐘后收費1元/min。內含項目文件(實測可運行),代碼,報告,視頻和照片,…

JavaScript函數定義,函數參數,函數調用

JavaScript函數定義: 在JavaScript中,我們可以使用關鍵字function來定義一個函數。函數定義的一般語法如下: function functionName(parameter1, parameter2, ...){// 函數體 }其中,functionName是函數的名稱,可以自定…

功能強大且專業的PDF轉換軟件PDF Shaper Professional 14.2

PDF Shaper Professional是一款適用于Windows的程序,可讓您在計算機上處理PDF文件。 要開始使用PDF Shaper Professional,您需要在Windows計算機上下載并安裝該程序。您還應該有合適的驅動程序和編解碼器來處理計算機上的文本和圖形。 安裝程序后&#…

分享一份糟糕透頂的簡歷,看看跟你寫的一樣不

最近看了一個人的簡歷,怎么說呢,前幾年這么寫沒問題,投出去就有回復,但從現在開始,這么寫肯定不行了。下面我給大家分享一下內容: 目錄 🤦?♀?這是簡歷文檔截圖 🤷?♀?這是基本…

淘寶評論API調用指南,讓你購物不再困擾

一、淘寶評論API概述 淘寶評論API是淘寶開放平臺提供的一種服務,它允許開發者通過調用API接口獲取淘寶商品評論數據,聯訊數據從而為用戶提供更加豐富和實用的購物決策信息。通過使用淘寶評論API,開發者可以輕松地實現以下功能: …

SwiftUI 利用 Swizz 黑魔法為系統創建的默認對象插入新協議方法(二)

功能需求 在 SwiftUI 的開發中,我們往往需要借助底層 UIKit 的“上帝之手”來進一步實現額外的定制功能。比如,在可拖放(Dragable)SwiftUI 的實現中,會缺失拖放取消的回調方法讓我們這些禿頭碼農們“欲哭無淚” 如上圖所示,我們在拖放取消時將界面中的一切改變都恢復如初…

slf4j等多個jar包沖突綁定的排查方法使用IDEA的maven help解決

1.安裝 2.使用maven help解決,找到對應包存在的沖突 使用exclude直接解決即可

【人工智能】第四部分:ChatGPT的技術實現

人不走空 🌈個人主頁:人不走空 💖系列專欄:算法專題 ?詩詞歌賦:斯是陋室,惟吾德馨 目錄 🌈個人主頁:人不走空 💖系列專欄:算法專題 ?詩詞歌…

dnf手游版游玩感悟

dnf手游于5月21號正式上線,作為一個dnf端游老玩家,并且偶爾上線ppk,自然下載了手游版,且玩了幾天。 不得不說dnf手游的優化做到了極好的程度。 就玩法系統這塊,因為dnf屬于城鎮地下城模式,相比…

前端工程化工具系列(三)—— Stylelint(v16.6.1):CSS/SCSS 代碼質量工具

Stylelint 是 CSS/SCSS 的靜態分析工具,用于檢查其中的違規和錯誤。 1. 環境要求 v16 以上的 Stylelint,支持 Node.js 的版本為 v18.12.0。 在命令行工具中輸入以下內容后回車,來查看當前系統中 Node.js 的版本。 node -vNode.js 推薦使用…

Shell腳本快速入門

為什么要學shell?能做什么? 答:CI/CD 持續集成,自動化部署作業方式,需要將一系列linux命令程序化,shell 就能做到。

13. 《C語言》——【strlen函數的使用和模擬實現】

文章目錄 前言strlen函數strlen函數的使用strlen函數的3種方法實現方法1方法2方法3 總結 前言 各位老板好~ , 今天我們講解strlen函數如何去使用以及如何去模擬實現strlen函數。希望各位老板能夠給一個點贊和一個大大的關注,感謝各位老板!str…

塑料焊接機熔深對激光焊接質量有什么影響

塑料焊接機的熔深對焊接質量具有直接且顯著的影響。以下是熔深對焊接質量影響的詳細解釋: 1. 焊接強度:熔深直接決定了焊縫的截面積,從而影響焊接接頭的強度。較深的熔深意味著焊縫的截面積更大,可以提供更強的結合力,…

OpenStreetMap部署(OSM)

參考:https://github.com/openstreetmap/openstreetmap-website/blob/master/DOCKER.md OpenStreeMap 部署 操作系統建議使用 Ubuntu 22 版本 安裝 Docker # 更新軟件包索引: sudo apt-get update # 允許APT使用HTTPS: sudo apt-get inst…

【計算機組成原理】詳談計算機發展歷程

計算機發展歷程 導讀一、計算機的誕生1.1 歷史背景1.2 計算機的發明 二、計算機硬件的發展1.1 計算機的四代變化1.1.1 第一代計算機bug的由來 1.1.2 第二代計算機1.1.3 第三代計算機半導體存儲器的發展 1.1.4 第四代計算機 1.2 個人計算機的發展1.2.1 微處理器的發展1.2.2 個人…