OceanBase 4.3.3 AP 解析:應用 RoaringBitmaps 類型處理海量數據的判重和基數統計

對于大數據開發人員而言,處理海量數據的判重操作和基數統計是常見需求,而 RoaringBitmap類型及其相關函數是當前非常高效的一種解決方案,許多大數據庫產品已支持RoaringBitmap類型。OceanBase 4.3.3版本,作為專為OLAP場景設計的正式發布(GA)版,也具備這一功能。本文重點闡述 RoaringBitmap 的原理、應用場景,并提供 OceanBase 中 RoaringBitmap 的應用示例。

RoaringBitmap 誕生背景簡介

海量數據的判重和基數統計需求,難度是數據量大且性能要盡可能好。技術方案的關鍵就是數據結構及其算法,數據結構也決定了其算法能力空間。

基礎的數據結構就是常用的數據類型,如數值、字符串、時間等。假設要業務數據數值化存儲,使用整型存儲(無符號),其表達的值域是 [0, 232-1],一共 4294967296 個數。如果記錄不重復且記錄數滿配,單就這一列會占用存儲空間16GB。這個判重方法有遍歷、排序加二分查找、BloomFilter 等。

所以后來有些場景會用Bitmap(位圖)存儲這個數據,每個位(bit)對應一行記錄的狀態(0表示不存在,1表示存在)。如果記錄不重復且記錄數滿配,這個位圖結構最大存儲空間是512MB。針對位圖的判重效率就非常高。

Bitmap 結構下在海量數據(40億+)的前提下,即使有大量數據重復也不會增加存儲空間和降低判重效率。位圖支持與運算(求交集)、或運算(求并集)。但是如果記錄數不多且重復值很高的情況下(學術界稱之為稀疏矩陣),Bitmap 存儲就有點浪費內存空間(固定 512MB)。于是學術界有提出稀疏位圖(或叫壓縮位圖)概念,Roaring Bitmap 就是稀疏位圖的實現方案中目前認為最好的方案,并且已經被多個數據庫產品支持。比如說 PostgreSQL 、AnalyticDB、PolarDB、Doris、ClickHouse、OceanBase (列舉的不一定全) 。

Roaring Bitmap 原理簡介

32 位地址空間容量下的數據值如果全用 Bitmap 存儲,碰到稀疏矩陣數據,為 0 的位會很多,很浪費存儲空間。RoaringBitmap 對這個 32 位使用做了一些改進,分為高 16 位和低 16 位。高 16 位做為記錄的索引 KEY,低 16 位作為記錄的值 VALUE。所以高 16 位有多少不同的記錄,就有多少個KEY,最多記錄數 216個。有的文章也把每個記錄稱之位一個 HASH Bucket(桶),每個 Bucket 的大小就是低 16 位存儲的記錄數。

低 16 位的數據結構分為三類。如果記錄數少于 4096 個,就使用 16 位的 Short Int 稀疏數組。名為數組,實際上是鏈表結構,以節省空間。如果記錄數超過 4096 個,就開始使用 16 位的 Bitmap 存儲。如果碰到連續的數據,則使用 Run Length Coding(簡稱 RLE)存儲一個開始和結束的整型值。

1730177610

Roaring Bitmap (后簡稱?rb)也支持兩個?rb?集合求并集、交集、差集、計算基數、排序等。這些操作是 SQL 運算邏輯的基礎。

OceanBase RoaringBitmap 類型和函數

OB 4.3.2 開始支持數據類型?roaringbitmap,以及相關函數。函數列表如下:

函數類型函數名稱函數作用
位圖構造函數rb_build_empty構建一個空的位圖數據。值為0x0100
rb_build_varbinaryVarbinary 為 OceanBase 私有格式,是由 version 信息、type 信息、data 等部分組成的二進制格式。
rb_from_string通過特定格式的字符串來構建位圖數據。字符串格式為需要構建的位圖數據的每一個元素,并通過逗號隔開,如 1,2,3,4。
位圖基數計算函數rb_cardinality返回輸入位圖數據的基數。
rb_and_cardinality rb_or_cardinality rb_andnot_cardinality返回兩個位圖數據做與計算后,得到的新位圖數據的基數。
rb_and_null2empty_cardinality rb_or_null2empty_cardinality rb_andnot_null2empty_cardinality返回兩個位圖數據做與計算后,得到的新位圖數據的基數。
rb_xor_cardinality返回兩個位圖數據做與計算后,得到的新位圖數據的基數。
位圖運算函數rb_and rb_and_null2empty計算兩個位圖數據的交集。
rb_or rb_or_null2empty計算兩個位圖數據的并集。
rb_xor提供兩個位圖數據的異或運算。
rb_andnot rb_andnot_null2empty提供兩個位圖數據的與非運算。
位圖判斷函數rb_is_empty判斷輸入的位圖數據是否為空。
位圖輸出函數rb_to_varbinary用于以 varbinary 的形式輸出位圖數據。
rb_to_string以字符串的形式依次輸出位圖數據的每一個元素,并以逗號隔開。其中元素的輸出格式為 UINT64,輸出的最大元素個數為 1000000。
位圖聚合函數rb_build_agg將數值列聚合為位圖數據。
rb_or_agg將位圖列的多行數據進行或運算,并聚合為位圖數據。
rb_and_agg將位圖列的多行數據進行與運算,并聚合為位圖數據。

OB Roaring Bitmap 示例

下面以用戶行為分析在 OB 的例子來演示這一功能。

首先構造基礎數據 用戶標簽表。

-- 用戶屬性表:共有100萬個用戶,每個用戶有64個屬性 --
create table t_user_tag (  
uid int8,   
tag int,        
mod_time timestamp,    
primary key (tag,uid)  
); DELIMITER //CREATE PROCEDURE insert_user_tag(IN min_uid BIGINT, IN max_uid BIGINT)
BEGINDECLARE uid BIGINT UNSIGNED;SET uid = min_uid;WHILE uid <= max_uid DO-- Loop to generate 64 random tags for each userINSERT IGNORE INTO t_user_tagSELECT uid, mod( rand(unix_timestamp())*1000000,1999), current_timestamp() from table(generator(64));  SET uid = uid + 1; -- Move to the next UIDEND WHILE;
END //DELIMITER ;call insert_user_tag(1,250000);
call insert_user_tag(250001,500000);
call insert_user_tag(500001,750000);
call insert_user_tag(750001,1000000);

然后生成標簽和用戶對應索引表,使用?roaringbitmap?類型。

create table t_tag_userbit (  tag int primary key,            userbit roaringbitmap,mod_time timestamp
);  insert /*+ enable_parallel_dml parallel(3) */ into t_tag_userbit 
select tag,rb_build_agg(uid),current_timestamp() from t_user_tag group by tag order by tag;

抽查幾筆數據看看?roaringbitmap?類型的數據特征。

select * from t_tag_userbit where tag in (1,11,111,1111);

1730177638

這里看到的是 dbeaver 工具格式化后的結果,實際?rb?列是二進制數據。

1730177648

如果是在命令行?mysqlobclient下,默認這個數據展示可能是亂碼,可以在命令行下加一個參數?--binary-as-hex?,使用十六進制展示 binary 類型數據。

obclient -h127.1 -P2881  -uroot@obmysql -p test --binary-as-hex

下面是一些?roaringbitmap?類型相關的函數演示。

比如格式化顯示和查看基數。

select tag, rb_to_string(userbit),rb_cardinality(userbit), mod_time 
from t_tag_userbit where tag in (1382, 1406,10257);

1730177665

計算同時滿足兩個tag標簽場景的的用戶數。

select rb_cardinality(rb_and_agg(userbit)) from t_tag_userbit  where tag in (1990,1998) ;

更新標簽用戶索引表。

update t_tag_userbit set userbit = rb_or(userbit, rb_from_string('61,71,73,74,85')) where tag = 1998;

看一下 SQL 執行計劃。

obclient [test]> explain select rb_cardinality(rb_and_agg(userbit)) from t_tag_userbit  where tag in (1002,1990,1998) ;
+-----------------------------------------------------------------------------------------------------+
| Query Plan                                                                                          |
+-----------------------------------------------------------------------------------------------------+
| ========================================================                                            |
| |ID|OPERATOR       |NAME         |EST.ROWS|EST.TIME(us)|                                            |
| --------------------------------------------------------                                            |
| |0 |SCALAR GROUP BY|             |1       |14          |                                            |
| |1 |└─TABLE GET    |t_tag_userbit|3       |14          |                                            |
| ========================================================                                            |
| Outputs & filters:                                                                                  |
| -------------------------------------                                                               |
|   0 - output([rb_cardinality(T_FUN_SYS_RB_AND_AGG(t_tag_userbit.userbit))]), filter(nil), rowset=16 |
|       group(nil), agg_func([T_FUN_SYS_RB_AND_AGG(t_tag_userbit.userbit)])                           |
|   1 - output([t_tag_userbit.userbit]), filter(nil), rowset=16                                       |
|       access([t_tag_userbit.userbit]), partitions(p0)                                               |
|       is_index_back=false, is_global_index=false,                                                   |
|       range_key([t_tag_userbit.tag]), range[1002 ; 1002], [1990 ; 1990], [1998 ; 1998],             |
|       range_cond([t_tag_userbit.tag IN (1002, 1990, 1998)])                                         |
+-----------------------------------------------------------------------------------------------------+
15 rows in set (0.041 sec)

從執行計劃看 SQL 引擎有跟 RB 有關的算子 :T_FUN_SYS_RB_AND_AGG?。

更多閱讀

OB 有了?roaringbitmap?類型,就也可以像 ClickHouse 一樣可以用于類似海量數據用戶標簽畫像等業務場景。


OceanBase? V4.3 現已支持 365天 免費試用,點擊立即開啟 >>?

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

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

相關文章

W25Qxx

概述 FLASH FLASH是一種是非易失性存儲器&#xff0c;即掉電后不會丟失數據&#xff0c;這和RAM&#xff08;隨機存儲器&#xff09;不同。 FLASH比起同作用的EEPROM有價格低的優點 FLASH的擦除操作是以扇區為單位的&#xff08;比起EEPROM來說操作較為不方便&#xff09; 芯片…

(滑動窗口)算法訓練篇11--力扣3.無重復字符的最長字串(難度中等)

目錄 1.題目鏈接&#xff1a;3.無重復字符的最長字符 2.題目描述&#xff1a; 3.解法(滑動窗口)&#xff1a; 1.題目鏈接&#xff1a;3.無重復字符的最長字符 2.題目描述&#xff1a; 給定一個字符串 s &#xff0c;請你找出其中不含有重復字符的 最長 子串 的長度。 示例…

深度學習1—Python基礎

深度學習1—python基礎 你的第一個程序 print(hello world and hello deep learning!)基本數據結構 空值 (None)&#xff1a;在 Python 中&#xff0c;None 是一個特殊的對象&#xff0c;用于表示空值或缺失的值。它不同于數字 0&#xff0c;因為 0 是一個有意義的數字&#…

記一次MyBatis分頁莫名其妙的失效,首次執行合適,后續執行分頁失效且異常

代碼幾乎一樣&#xff0c;為啥這個xml配置的就會出現莫名其妙的問題呢 org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.type.TypeException: Could not set parameters for mapping: ParameterMapping{propertymybatis_plus_first, modeI…

網絡不可達

導致此問題原因較多&#xff0c;我只針對一種情況進行討論&#xff0c;如果和文中癥狀不同&#xff0c;另尋他處&#xff0c;或者死馬當活馬醫&#xff08;&#xff1f;&#xff09; 如需轉載&#xff0c;標記出處 癥狀&#xff1a; 1.ping命令網絡不可達 2.ifconfig中網卡en…

【AI News | 20250322】每日AI進展

AI Repos 1、DeTikZify 可以把草圖或圖形轉換成TikZ代碼的模型&#xff0c;可用來繪制復雜的科學圖表&#xff0c;輸入草圖或文字描述即可轉換成TikZ代碼。DeTikZify強大的地方在于它能理解圖表的語義信息&#xff0c; 能識別圖表中的不同組成部分及其含義&#xff0c;比如坐標…

Debian12生產環境配置筆記

在 Debian 12 上進行生產環境配置的詳細步驟&#xff0c;涵蓋軟件更新、基礎軟件安裝、Docker 及 Redis 部署&#xff0c;以及 Nginx 配置多個虛擬主機等內容。所有命令均以 root 用戶身份執行&#xff0c;無需添加 sudo 1. 更新軟件 首先&#xff0c;確保系統上的所有軟件包…

UE AI 模型自動生成導入場景中

打開小馬的weix 關注下 搜索“技術鏈” 回復《《動畫》》 快速推送&#xff1b; 拿到就能用輕松解決&#xff01;幫忙點個關注吧&#xff01;

【最后203篇系列】022 用Deepseek14b提取新聞事件

這算是之前一直想做的一件事&#xff0c;趁周末趕快做了。 業務意義&#xff1a;現實中有大量的輿情&#xff0c;這對我們的決策會有比較重要的作用 技術依賴&#xff1a; 1 模型基礎能力2 消息隊列3 異步獲取消息4 時間序列庫 1 模型基礎能力 大模型發展到現在&#xff0…

電池電量檢測方法介紹,開路電壓法、庫侖積分法、內阻法

開路電壓法、庫侖積分法、內阻法、卡爾曼濾波法、混合法 開路電壓法是目前最簡單的方法&#xff0c;根據電池的特性得知&#xff0c;在電池容量與開路電壓之間存在一定的函數關系&#xff0c;當得知開路電壓時&#xff0c;可以初步估算電池的剩余電量。該方法精度不高&#xf…

微調實戰 - 使用 Unsloth 微調 QwQ 32B 4bit (單卡4090)

本文參考視頻教程&#xff1a;賦范課堂 – 只需20G顯存&#xff0c;QwQ-32B高效微調實戰&#xff01;4大微調工具精講&#xff01;知識灌注問答風格微調&#xff0c;DeepSeek R1類推理模型微調Cot數據集創建實戰打造定制大模型&#xff01; https://www.bilibili.com/video/BV1…

【Elasticsearch】基于 Word2Vec 實現文章抄襲檢測

?? 博主簡介:CSDN博客專家,歷代文學網(PC端可以訪問:https://literature.sinhy.com/#/literature?__c=1000,移動端可微信小程序搜索“歷代文學”)總架構師,15年工作經驗,精通Java編程,高并發設計,Springboot和微服務,熟悉Linux,ESXI虛擬化以及云原生Docker和K8s…

多層感知機與反向傳播

1. 多層感知機&#xff08;MLP&#xff09; 多層感知機是一個由多個層組成的神經網絡&#xff0c;包括輸入層、隱藏層和輸出層。它的目標是通過學習輸入數據和輸出結果之間的關系&#xff0c;來解決各種問題&#xff08;比如分類或回歸&#xff09;。 2. 反向傳播&#xff08…

Cursor的五種高級用法

文章目錄 代碼編寫寫作編輯自動生成工作流搞定開源項目數據處理參考 代碼編寫 Cursor 最基本的功能是幫助你編寫代碼。只需使用 Composer&#xff08;CtrlI&#xff09;&#xff0c;描述你想要實現的功能&#xff0c;Cursor 就能生成相應的代碼。不滿意&#xff1f;直接告訴它…

LeetCode hot 100 每日一題(13)——73. 矩陣置零

這是一道難度為中等的題目&#xff0c;讓我們來看看題目描述&#xff1a; 給定一個 _m_ x _n_ 的矩陣&#xff0c;如果一個元素為 0 &#xff0c;則將其所在行和列的所有元素都設為 0 。請使用 原地 算法。 提示&#xff1a; m matrix.lengthn matrix[0].length1 < m, n …

Java基礎編程練習第34題-正則表達式

在Java里&#xff0c;正則表達式是一種強大的文本處理工具&#xff0c;它可以用于字符串的搜索、替換、分割和校驗等操作。正則表達式使用單個字符串來描述、匹配一系列符合某個句法規則的字符串。Java通過java.util.regex包提供了對正則表達式的支持。 以下是正則表達式在Jav…

基于基于eFish-SBC-RK3576工控板的智慧城市邊緣網關

此方案充分挖掘eFish-SBC-RK3576的硬件潛力&#xff0c;可快速復制到智慧園區、交通樞紐等場景。 方案亮點 ?接口高密度?&#xff1a;單板集成5GWiFi多路工業接口&#xff0c;減少擴展復雜度。?AIoT融合?&#xff1a;邊緣端完成傳感器數據聚合與AI推理&#xff0c;降低云端…

redis解決緩存穿透/擊穿/雪崩

文章目錄 1.緩存穿透1.1 概念1.2 解決方案1.2.1 緩存空對象1.2.2 布隆過濾 1.2 店鋪查詢使用緩存穿透解決方案1.2.1 流程 2.緩存雪崩2.1 什么是緩存雪崩&#xff1f;2.2 雪崩解決方案 3.緩存擊穿3.1 什么是緩存擊穿&#xff1f;3.2解決方案3.2.1 基于互斥鎖解決緩存擊穿問題&am…

第十六屆藍橋杯康復訓練--6

題目鏈接&#xff1a;790. 數的三次方根 - AcWing題庫 思路&#xff1a;二分&#xff0c;注意正負號和小數判斷退出的方法&#xff08;雖然正負無所謂&#xff09; 代碼&#xff1a; #include<bits/stdc.h> using namespace std;#define exs 0.00000018812716007232667…

Vue學習筆記集--路由

路由 Vue Router 是 Vue.js 官方的路由管理器&#xff0c;用于在 Vue 應用程序中實現單頁面應用&#xff08;SPA&#xff09;的路由功能。以下是 Vue Router 的基本使用方法&#xff1a; 安裝 Vue Router 如果你使用的是 Vue 2&#xff0c;可以通過 npm 安裝 Vue Router&…