亚欧色一区w666天堂,色情一区二区三区免费看,少妇特黄A片一区二区三区,亚洲人成网站999久久久综合,国产av熟女一区二区三区

  • 發布文章
  • 消息中心
點贊
收藏
評論
分享
原創

doris索引原理及使用場景

2023-07-26 01:33:49
375
0

1.概述

索引和底(di)層存(cun)儲(chu)息(xi)(xi)息(xi)(xi)相關,doris采用LSM的(de)(de)(de)(de)存(cun)儲(chu)結(jie)構,數(shu)據(ju)(ju)首先會(hui)寫入(ru)Tablet對應的(de)(de)(de)(de)memtable中,memtable寫滿之(zhi)后,數(shu)據(ju)(ju)會(hui)flush寫入(ru)磁(ci)盤,形(xing)成一(yi)個個不可變的(de)(de)(de)(de)segment文件, 由于(yu)memtable用的(de)(de)(de)(de)是skiplist數(shu)據(ju)(ju)結(jie)構,skiplist數(shu)據(ju)(ju)是按(an)照(zhao)key排(pai)序的(de)(de)(de)(de),所以flush到(dao)磁(ci)盤的(de)(de)(de)(de)segment文件也(ye)是按(an)照(zhao)key排(pai)序的(de)(de)(de)(de),doris底(di)層是按(an)照(zhao)列(lie)(lie)存(cun)儲(chu)數(shu)據(ju)(ju)的(de)(de)(de)(de),存(cun)儲(chu)在一(yi)種SST的(de)(de)(de)(de)數(shu)據(ju)(ju)結(jie)構中,每列(lie)(lie)數(shu)據(ju)(ju)會(hui)被(bei)分為(wei)多個data page。

數據從memtable flush到磁盤分為兩個階段:

 1.將memtable中的(de)行存結構(gou)轉換為(wei)列(lie)存結構(gou),并為(wei)每一列(lie)生成對應的(de)索引結構(gou)

 2.將轉換后(hou)的列存結構寫入磁(ci)盤,生成segment文件。

segment文(wen)件(jian)分(fen)為數據區(qu)域、索引區(qu)域和footer三個部分(fen),如下圖所示(shi):

說明:

data region: 存儲各個列的數(shu)據(ju)信息,每列數(shu)據(ju)被分(fen)為多(duo)個data page。

index region: Doris 中將各個列的(de) index 數據(ju)統一(yi)存儲(chu)在 Index Region,這里(li)的(de)數據(ju)會按(an)照列粒度進行加載(zai),所以跟(gen)列的(de)數據(ju)信息分開存儲(chu)

footer信息

footer信息(xi)段在文件的尾部,存儲了文件的整(zheng)體結構(gou),包括數據域和索(suo)引域的位置等(deng),共(gong)分(fen)(fen)為SegmentFooterPB,CheckSum,Length,MAGIC CODE 4 個部分(fen)(fen)。

segementFooterPB定義了元(yuan)數(shu)據信(xin)息(xi)(xi),包(bao)括列的元(yuan)數(shu)據信(xin)息(xi)(xi),索引(yin)的元(yuan)數(shu)據信(xin)息(xi)(xi),前綴(zhui)索引(yin)信(xin)息(xi)(xi),總行數(shu)等,數(shu)據結構如下(xia):

 

2.索引

目前 Doris 主(zhu)要支持兩類(lei)索(suo)引:

  1. 內建的智能索引,包括前綴索引和 ZoneMap 索引。
  2. 用戶手動創建的二級索引,包括 倒排索引、 bloomfilter索引、 ngram bloomfilter索引 和bitmap索引

2.1前綴索引

Doris 不支持在任(ren)意列上(shang)創建索引。Doris 這類 MPP 架構的(de) OLAP 數(shu)據(ju)庫(ku),通常都(dou)是通過提高(gao)并發,來處理(li)大量數(shu)據(ju)的(de)。

本(ben)質上(shang),Doris 的數據(ju)存(cun)儲在類似 SSTable(Sorted String Table)的數據(ju)結構(gou)中。該(gai)結構(gou)是一種有序的數據(ju)結構(gou),可以按照指定的列進(jin)行排序存(cun)儲。在這種數據(ju)結構(gou)上(shang),以排序列作為條件進(jin)行查找,會非(fei)常的高效(xiao)。

在 Aggregate、Unique 和 Duplicate 三種數(shu)據(ju)模型中(zhong)。底(di)層的(de)(de)數(shu)據(ju)存儲,是按(an)照各自建表語句(ju)中(zhong),AGGREGATE KEY、UNIQUE KEY 和 DUPLICATE KEY 中(zhong)指定的(de)(de)列進行排序存儲的(de)(de)。

而前綴(zhui)索(suo)引(yin),即(ji)在排序(xu)的基(ji)礎上,實現的一種根據給定前綴(zhui)列,快速(su)查詢數據的索(suo)引(yin)方式。前綴(zhui)索(suo)引(yin)又(you)叫Short Key Index。

2.1.1存儲結構

前(qian)(qian)綴索(suo)(suo)引(yin)是(shi)一種稀疏(shu)索(suo)(suo)引(yin),數(shu)據寫入過程中,每隔(ge)1024行(xing)會(hui)生成一個(ge)(ge)索(suo)(suo)引(yin)項(xiang),前(qian)(qian)綴索(suo)(suo)引(yin)會(hui)對(dui)每一個(ge)(ge)索(suo)(suo)引(yin)間隔(ge)的(de)(de)第一個(ge)(ge)數(shu)據行(xing)的(de)(de)前(qian)(qian)綴字段(duan)進(jin)行(xing)編碼,前(qian)(qian)綴字段(duan)的(de)(de)編碼與前(qian)(qian)綴字段(duan)的(de)(de)值具有相同的(de)(de)排(pai)序(xu)(xu)規則,即前(qian)(qian)綴字段(duan)的(de)(de)值排(pai)序(xu)(xu)越(yue)靠前(qian)(qian),對(dui)應的(de)(de)編碼值排(pai)序(xu)(xu)也(ye)越(yue)靠前(qian)(qian)。Segment 文件是(shi)按 Key 排(pai)序(xu)(xu)的(de)(de),因此,前(qian)(qian)綴索(suo)(suo)引(yin)項(xiang)也(ye)是(shi)按 Key 排(pai)序(xu)(xu)的(de)(de)。

一個 Segment 文件中的前綴索引數據保存在一個獨立的 Short Key Page 中,其中包含每一條前綴索引項的編碼數據、每一條前綴索引項的 offset、Short Key Page 的 footer 以及 Short Key Page 的 Checksum 信息。Short Key Page 的 footer 中記錄了 Page 的類型、前綴索引編碼數據的大小、前綴索引 offset 數據的大小、前綴索引項的數目等信息

Short Key Page 在 Segment 中的 offset 和大小會被保存在Segment文件的footer中,以便于數(shu)據讀(du)取時(shi)能夠正確地從Segment文件中加載出前(qian)綴(zhui)索引(yin)數(shu)據。前(qian)綴(zhui)索引(yin)的存儲(chu)結(jie)構如圖所示:

 

查詢(xun)時會先打開segment文件,然(ran)后在segment footer中找到short key page的offset及大小,然(ran)后讀(du)取對應的short key page中索引數據(ju),并(bing)解析每一(yi)條前綴索引項。

2.1.2索引生成規則

doris將一(yi)行數據的前36個(ge)字節作為前綴(zhui)索引,如果遇到varchar類(lei)型,前綴(zhui)索引會直接(jie)截斷,

2.1.3應用案例

  1. 以下(xia)表結構的前綴索引為 user_id(8 Bytes) + age(4 Bytes) + message(prefix 20 Bytes)。

    ColumnName Type
    user_id BIGINT
    age INT
    message VARCHAR(100)
    max_dwell_time DATETIME
    min_dwell_time DATETIME
  2. 以下表結構的前綴索引為(wei)(wei) user_name(20 Bytes)。即使沒有達到 36 個(ge)字節,因為(wei)(wei)遇到 VARCHAR,所以直接截斷,不再往(wang)后繼續。

    ColumnName Type
    user_name VARCHAR(20)
    age INT
    message VARCHAR(100)
    max_dwell_time DATETIME
    min_dwell_time DATETIME

當我們的查詢條件,是前綴索引的前綴時,可以極大的加快查詢速度。比(bi)如在第(di)一個(ge)例子中,我(wo)們執行如下查詢:

SELECT * FROM table WHERE user_id=1829239 and age=20;
 

該查詢的效率會遠高于如下查詢:

SELECT * FROM table WHERE age=20;
 

所以在建表時,正確的選擇列順序,能夠極大地提高查詢效率

 

2.2 Zone Map 索引

segment中的(de)每(mei)列(lie)數(shu)據和(he)列(lie)中的(de)每(mei)個(ge)data page也會(hui)(hui)有(you)zone map索引項,zone map索引記(ji)錄(lu)每(mei)列(lie)及(ji)列(lie)中每(mei)個(ge)data page的(de)最(zui)大(da)值(max value)最(zui)小值(min value),是否(fou)有(you)Null值(has null),是否(fou)有(you)非Null值(has not null)等信息(xi)。初始化時(數(shu)據為(wei)(wei)空時),max value會(hui)(hui)被(bei)設置為(wei)(wei)當前(qian)列(lie)類型的(de)最(zui)小值, min value會(hui)(hui)被(bei)設置為(wei)(wei)當前(qian)列(lie)類型的(de)最(zui)大(da)值,has null和(he)has not null均為(wei)(wei)false.

2.2.1索引生成規則

doris默認為key列(AGGREGATE KEY、UNIQ KEY 和 DUPLICATE KEY)開啟(qi)ZoneMap索(suo)引,當表模型為 DUPULCATE 時,所有字段會(hui)開啟(qi) ZoneMap 索(suo)引。

數據寫入時(shi),會給data page生成zone map索(suo)引(yin),當data page中有數據更(geng)新(xin)時(shi),對應的(de)zone map索(suo)引(yin)也要更(geng)新(xin)。更(geng)新(xin)規則如下:

 1.如(ru)果新增的(de)數據為null, 則(ze)has null=true, 否則(ze)has not null=true

 2.如果(guo)新(xin)增(zeng)數(shu)據(ju)小于(yu)(yu)zone map索引(yin)中(zhong)的(de)min value,則(ze)使用(yong)當前(qian)數(shu)據(ju)更新(xin)min value, 如果(guo)新(xin)增(zeng)數(shu)據(ju)大于(yu)(yu)zone map索引(yin)中(zhong)的(de)max value,則(ze)使用(yong)當前(qian)數(shu)據(ju)更新(xin)max value.

當一個Data Page寫滿之后,不僅會更新當前data page的zone map索引,也會更新data page所在列的索引。

2.2.2 應用

在查詢過(guo)程中,范圍條件(jian)過(guo)濾字(zi)段會根據(ju)zone map索引中的統計信(xin)息選取掃描的數(shu)據(ju)范圍。

查詢如下:

SELECT * FROM table WHERE age > 20 and age < 1000

在沒有命中 Short Key Index 的(de)(de)情(qing)況下(xia),會(hui)根據(ju)條件語(yu)句中 age 的(de)(de)查詢條件,利用 ZoneMap 索(suo)引(yin)找到應該掃(sao)描的(de)(de)數據(ju) ordinary 范圍,減少要掃(sao)描的(de)(de) page 數量。

 

2.3 Ordinal 索引

2.3.1索引生成規則

Doris 底層采用列存(cun)的方式來(lai)存(cun)儲數據(ju),每一列數據(ju)會被分(fen)為多(duo)個Data Page。

數(shu)據(ju)刷寫(xie)時(shi),會(hui)為每一個Data Page生(sheng)成(cheng)一條Ordinal索引項(xiang),該(gai)索引項(xiang)保(bao)存Data Page在(zai)Segment文件中(zhong)的(de)offset、Data Page的(de)大小以(yi)及(ji)Data Page的(de)起始(shi)行(xing)號,所有Data Page的(de)Ordinal索引項(xiang)會(hui)保(bao)存在(zai)一個Ordinal Index Page中(zhong), Ordinal Index Page在(zai)Segment文件中(zhong)的(de)offset以(yi)及(ji)Ordinal Index Page的(de)大小會(hui)被保(bao)存在(zai)Segment文件的(de)footer中(zhong),以(yi)便于數(shu)據(ju)讀取時(shi)能夠通(tong)過(guo)兩級索引找到(dao)Data Page(首先,通(tong)過(guo)Segment文件的(de)footer找到(dao)Ordinal Index Page,然后(hou),通(tong)過(guo)Ordinal Index Page中(zhong)的(de)索引項(xiang)找到(dao)Data Page)。

Ordinal Index Page包(bao)含(han)以下(xia)信息:所(suo)有Ordinal索(suo)(suo)引(yin)項(xiang)數(shu)據、Ordinal Index Page的(de)(de)footer以及Short Key Page的(de)(de)Checksum信息。Ordinal Index Page的(de)(de)footer中包(bao)含(han)當前(qian)Page的(de)(de)類型、Ordinal索(suo)(suo)引(yin)項(xiang)數(shu)據的(de)(de)大小(xiao)、Ordinal索(suo)(suo)引(yin)項(xiang)數(shu)目等信息。

如(ru)果列中(zhong)(zhong)只(zhi)有一(yi)個Data Page時,即該列只(zhi)有一(yi)條Ordinal索引(yin)項,則Segment文(wen)(wen)件中(zhong)(zhong)不需(xu)要保存該列的(de)Ordinal索引(yin)數(shu)據(ju)(ju),只(zhi)需(xu)要將這(zhe)唯一(yi)的(de)Data Page在(zai)Segment文(wen)(wen)件中(zhong)(zhong)的(de)offset以及該Data Page的(de)大小保存在(zai)Segment文(wen)(wen)件的(de)footer中(zhong)(zhong)。數(shu)據(ju)(ju)讀取時可以通過Segment文(wen)(wen)件的(de)footer直(zhi)接找到這(zhe)唯一(yi)的(de)Data Page。Ordinal索引(yin)的(de)存儲(chu)結構如(ru)圖3所示。

Ordinal索引(yin)的(de)作用是(shi)為了方(fang)便(bian)其他類型(xing)的(de)索引(yin)能夠使用統一的(de)方(fang)式(shi)查找Data Page,進而可以對其他類型(xing)的(de)索引(yin)屏蔽Data Page在Segment文(wen)件中的(de)offset

2.3.2查詢過濾

查(cha)詢時(shi),會(hui)加載每一個列(lie)(lie)的(de)Ordinal索(suo)引數據(ju)。通(tong)過Segment footer中記(ji)錄的(de)Ordinal索(suo)引的(de)Meta信息判(pan)斷當前(qian)(qian)列(lie)(lie)是否(fou)存在Ordinal Index Page,即(ji)判(pan)斷當前(qian)(qian)列(lie)(lie)是否(fou)有多個Data Page。

如果(guo)當前列存(cun)在(zai)Ordinal Index Page,則從(cong)Segment footer中獲(huo)取(qu)Ordinal Index Page在(zai)Segment中的(de)offset和(he)Ordinal Index Page的(de)大小(xiao),然(ran)后從(cong)Segment文件中讀取(qu)Ordinal Index Page數據,并解析出(chu)每一條Ordinal索(suo)引(yin)項,即可通過Ordinal索(suo)引(yin)項獲(huo)取(qu)當前列中每一個Data Page的(de)起(qi)始行號(hao)、Data Page在(zai)Segment中的(de)offset以及Data Page的(de)大小(xiao)。

如果當前(qian)列(lie)(lie)不存在Ordinal Index Page,則(ze)可以(yi)直(zhi)接從Segment footer中獲取當前(qian)列(lie)(lie)中唯一的(de)(de)Data Page在Segment中的(de)(de)offset以(yi)及Data Page的(de)(de)大小。

 

2.4 BitMap索引

為(wei)了加速查詢,doris支(zhi)持用戶為(wei)字段創(chuang)建Bitmap索引,Bitmap索引由(you)兩(liang)部分(fen)組成(cheng):

  1.有序字典:有序保存(cun)一列中所有的不同取(qu)值。

  2.字(zi)典(dian)(dian)的(de)(de)位圖:保存有(you)序字(zi)典(dian)(dian)中(zhong)每一個值的(de)(de)位圖,值是(shi)字(zi)典(dian)(dian)值在列中(zhong)的(de)(de)行(xing)號。

一列數據(ju)(ju)為(wei)[x, x, y, y, y, z, y, x, z, x],一共包含10行,則(ze)該列數據(ju)(ju)的(de)Bitmap索引的(de)有序(xu)字典為(wei){x, y, z}, 其中x、y、z對應的(de)位圖分別為(wei):

x的位圖: [0, 1, 7, 9]

y的位圖: [2, 3, 4, 6]

z的位圖: [5, 8]

如下圖所示:

左側為有序(xu)字典,右側為字典每一個元素對應的位圖。

 

2.4.1 索引生成規則

數據(ju)刷(shua)寫時,會(hui)給用戶指定的(de)(de)(de)列(lie)(lie)創建Bitmap索引(yin)(yin)。向列(lie)(lie)中每添加(jia)一個值(zhi)(zhi)(zhi)(zhi),都(dou)會(hui)更新(xin)當前列(lie)(lie)的(de)(de)(de)BitMap索引(yin)(yin)。從Bitmap索引(yin)(yin)對應的(de)(de)(de)有(you)序字典查找新(xin)添加(jia)的(de)(de)(de)值(zhi)(zhi)(zhi)(zhi)是否存(cun)在(zai),如果(guo)已經(jing)存(cun)在(zai),則只更新(xin)該字典值(zhi)(zhi)(zhi)(zhi)對應的(de)(de)(de)位(wei)圖(tu)(tu)(tu);如果(guo)不存(cun)在(zai),則將(jiang)該值(zhi)(zhi)(zhi)(zhi)添加(jia)到有(you)序字典中,并為(wei)這(zhe)個值(zhi)(zhi)(zhi)(zhi)生成(cheng)位(wei)圖(tu)(tu)(tu),Null值(zhi)(zhi)(zhi)(zhi)也(ye)會(hui)有(you)單獨(du)的(de)(de)(de)位(wei)圖(tu)(tu)(tu)。可(ke)以看出Bitmap只適合低基數的(de)(de)(de)列(lie)(lie),如果(guo)基數很高,生成(cheng)大量的(de)(de)(de)位(wei)圖(tu)(tu)(tu)會(hui)占用巨(ju)大的(de)(de)(de)空(kong)間(jian)。

Bitmap索引的(de)字典數據和位圖數據分(fen)開存(cun)儲。

字(zi)典(dian)數(shu)據存(cun)(cun)儲(chu)在(zai)(zai)對應的(de)(de)dict page中(zhong)(zhong),位圖(tu)數(shu)據存(cun)(cun)儲(chu)在(zai)(zai)對應的(de)(de)Bitmap page中(zhong)(zhong),而(er)dict page和(he)Bitmap page的(de)(de)元信(xin)息(xi)會記錄(lu)在(zai)(zai)segment footer中(zhong)(zhong)。如果一(yi)個(ge)(ge)列有多個(ge)(ge)dict page則會轉化成兩級(ji)索引(yin),第二級(ji)索引(yin)為(wei)多個(ge)(ge)dict page,保存(cun)(cun)字(zi)典(dian)數(shu)據,每一(yi)個(ge)(ge)dict page生(sheng)成一(yi)條value索引(yin)項,所有dict page的(de)(de)value 索引(yin)項會被(bei)被(bei)保存(cun)(cun)在(zai)(zai)一(yi)個(ge)(ge)value index page中(zhong)(zhong)作為(wei)一(yi)級(ji)索引(yin),每一(yi)個(ge)(ge)的(de)(de)Value索引(yin)項記錄(lu)了(le)當前(qian)Dict Page中(zhong)(zhong)第一(yi)個(ge)(ge)字(zi)典(dian)值的(de)(de)編碼以(yi)及當前(qian)Dict Page在(zai)(zai)Segment文件中(zhong)(zhong)的(de)(de)offset和(he)大(da)小(xiao),而(er)value index page的(de)(de)元信(xin)息(xi)則保存(cun)(cun)在(zai)(zai)segment footer中(zhong)(zhong)。

同(tong)理如果一(yi)個(ge)(ge)列有多個(ge)(ge)Bitmap page則(ze)會(hui)轉(zhuan)化成(cheng)二級(ji)(ji)索引(yin)(yin),第二級(ji)(ji)索引(yin)(yin)為(wei)多個(ge)(ge)的(de)Bitmap Page,其中(zhong)保(bao)存(cun)Bitmap索引(yin)(yin)的(de)位圖數據,每一(yi)個(ge)(ge)Bitmap Page生成(cheng)一(yi)條Ordinal索引(yin)(yin)項(xiang),所有Bitmap Page的(de)Ordinal索引(yin)(yin)項(xiang)會(hui)被保(bao)存(cun)在一(yi)個(ge)(ge)Ordinal Index Page(注意,此(ci)處(chu)的(de)Ordinal 索引(yin)(yin)與第3部(bu)分(fen)的(de)Ordinal 索引(yin)(yin)不同(tong),此(ci)處(chu)的(de)Ordinal 索引(yin)(yin)指向Bitmap Page,而第3部(bu)分(fen)的(de)Ordinal 索引(yin)(yin)指向Data Page)中(zhong)作為(wei)一(yi)級(ji)(ji)索引(yin)(yin),而Ordinal Index Page的(de)元(yuan)信息則(ze)保(bao)存(cun)在segment footer中(zhong)。

2.4.2適用場景

Doris支(zhi)持在(zai)建(jian)表(biao)時(shi)對(dui)指定的列創(chuang)建(jian)Bitmap索(suo)引,也可以對(dui)已經創(chuang)建(jian)的表(biao)執(zhi)行Alter Table命(ming)令(ling)添(tian)加Bitmap索(suo)引。

ALTER TABLE table_name ADD INDEX index_name (column_name) USING BITMAP COMMENT ‘’;

目(mu)前只支持(chi)對(dui)TINYINT、SMALLINT、INT、 UNSIGNEDINT、BIGINT、LARGEINT、CHAR、 VARCHAR、DATE、DATETIME、BOOL和DECIMAL類(lei)型(xing)的字段(duan)創建Bitmap索(suo)引,其他(ta)類(lei)型(xing)的字段(duan)均(jun)不(bu)支持(chi)Bitmap索(suo)引。

Bitmap索引比(bi)較適合在基(ji)數較低的列上進行(xing)等值查(cha)詢或范(fan)圍查(cha)詢的場景(jing)

 

2.5 Bloom Filter索引

Bloom Filter索引(yin)按照Data Page的(de)粒度生成(cheng)。數(shu)(shu)據寫(xie)(xie)入(ru)(ru)時(shi)(shi)(shi),會記(ji)錄每一個寫(xie)(xie)入(ru)(ru)Data Page的(de)值(zhi),當一個Data Page寫(xie)(xie)滿(man)之后,會根(gen)據該(gai)Data Page的(de)所有(you)不同取(qu)(qu)值(zhi)為該(gai)Data Page生成(cheng)Bloom Filter索引(yin)。數(shu)(shu)據查(cha)詢時(shi)(shi)(shi),查(cha)詢條件在設置(zhi)有(you)Bloom Filter索引(yin)的(de)字段進(jin)行(xing)過(guo)濾,當某個Data Page的(de)Bloom Filter沒有(you)命(ming)中時(shi)(shi)(shi),表示(shi)該(gai)Data Page中沒有(you)需要(yao)的(de)數(shu)(shu)據,這樣可(ke)以對Data Page進(jin)行(xing)快(kuai)速過(guo)濾,減少不必要(yao)的(de)數(shu)(shu)據讀(du)取(qu)(qu)。

 

2.5.1適用場景

Doris支持在建(jian)表時對(dui)指定的列創建(jian)Bloom Filter索(suo)引,也可以對(dui)已經創建(jian)的表執行Alter Table命令添加Bloom Filter索(suo)引。

ALTER TABLE table_name SET (“bloom_filter_columns”=”c1, c2, c3”);

目前只支持(chi)對(dui)SMALLINT、INT、UNSIGNEDINT、 BIGINT、LARGEINT、CHAR、 VARCHAR、DATE、DATETIME和DECIMAL類型的(de)(de)字段(duan)創建Bloom Filter索(suo)引,其他類型的(de)(de)字段(duan)均不支持(chi)Bloom Filter索(suo)引。對(dui)于創建了Bloom Filter索(suo)引的(de)(de)字段(duan),查(cha)詢條件是”=”、”is”或”in”語句(ju)時,才會使用Bloom Filter索(suo)引進(jin)行Data Page的(de)(de)過(guo)濾。Bloom Filter索(suo)引比較適合在(zai)基數較高的(de)(de)列上進(jin)行等值查(cha)詢的(de)(de)場景。

 

2.6NGram BloomFilter索引

為了(le)提升like的查詢(xun)性能,增加(jia)了(le)NGram BloomFilter索引。

2.6.1 NGram BloomFilter創建?

表創建時指定:

CREATE TABLE `table3` (
`siteid` int(11) NULL DEFAULT "10" COMMENT "",
`citycode` smallint(6) NULL COMMENT "",
`username` varchar(32) NULL DEFAULT "" COMMENT "",
INDEX idx_ngrambf (`username`) USING NGRAM_BF PROPERTIES("gram_size"="3", "bf_size"="256") COMMENT 'username ngram_bf index'
) ENGINE=OLAP
AGGREGATE KEY(`siteid`, `citycode`, `username`) COMMENT "OLAP"
DISTRIBUTED BY HASH(`siteid`) BUCKETS 10
PROPERTIES (
"replication_num" = "1"
);

-- PROPERTIES("gram_size"="3", "bf_size"="256"),分(fen)別表(biao)示gram的(de)個數和(he)bloom filter的(de)字節數。
-- gram的(de)個數(shu)(shu)跟實際查(cha)詢場景相(xiang)關,通(tong)常(chang)設置(zhi)為大部(bu)分查(cha)詢字符(fu)串的(de)長度,bloom filter字節數(shu)(shu),可以通(tong)過(guo)測試(shi)得出,通(tong)常(chang)越(yue)(yue)大過(guo)濾效果越(yue)(yue)好,可以從256開始進(jin)行驗證測試(shi)看(kan)看(kan)效果。當然字節數(shu)(shu)越(yue)(yue)大也會帶(dai)來索引(yin)存儲、內(nei)存cost上升。
-- 如果數據(ju)基(ji)數比較高(gao),字節數可以不用設置過(guo)大,如果基(ji)數不是(shi)很(hen)高(gao),可以通(tong)過(guo)增加字節數來(lai)提升過(guo)濾效(xiao)果。

2.6.2 NGram BloomFilter使用注意事項?

  1. NGram BloomFilter只支持字符串列
  2. NGram BloomFilter索引和BloomFilter索引為互斥關系,即同一個列只能設置兩者中的一個
  3. NGram大小和BloomFilter的字節數,可以根據實際情況調優,如果NGram比較小,可以適當增加BloomFilter大小
  4. 如果要查看某個查詢是否命中了NGram Bloom Filter索引,可以通過查詢的Profile信息查看

 

2.7 倒排索引

從2.0.0版本(ben)(ben)開(kai)始,Doris支(zhi)持倒排索(suo)引,可以用來(lai)進(jin)行(xing)文(wen)(wen)(wen)本(ben)(ben)類(lei)型的全文(wen)(wen)(wen)檢索(suo)、普通數值日期類(lei)型的等值范圍(wei)查詢,快(kuai)速從海(hai)量數據(ju)中過濾出(chu)滿足條(tiao)件的行(xing)。本(ben)(ben)文(wen)(wen)(wen)檔主要(yao)介紹如何倒排索(suo)引的創建、刪除、查詢等使用方式。

inverted index倒排索引,是信息檢索領域常用的索引技術(shu),將文本(ben)分割成一個(ge)(ge)個(ge)(ge)詞,構(gou)建 詞 -> 文檔編號(hao) 的索引,可以快速查(cha)找(zhao)一個(ge)(ge)詞在哪些(xie)文檔出(chu)現。

在Doris的(de)倒排(pai)索引實現(xian)中,table的(de)一行(xing)對應一個文檔(dang)、一列(lie)對應文檔(dang)中的(de)一個字段,因此利用倒排(pai)索引可以(yi)根(gen)據關鍵詞快速定位包含它的(de)行(xing),達到WHERE子句(ju)加速的(de)目(mu)的(de)。

與Doris中其他索(suo)引(yin)不同(tong)的(de)(de)是,在(zai)存儲層倒排索(suo)引(yin)使用獨立的(de)(de)文(wen)件,跟segment文(wen)件有邏輯對應關系、但存儲的(de)(de)文(wen)件相互獨立。這樣的(de)(de)好處(chu)是可以做到創建、刪除索(suo)引(yin)不用重寫tablet和segment文(wen)件,大幅降低處(chu)理開銷。

 

2.7.1 功能

  • 增加了字符串類型的全文檢索
    • 支持字符串全文檢索,包括同時匹配多個關鍵字MATCH_ALL、匹配任意一個關鍵字MATCH_ANY、匹配短語詞組MATCH_PHRASE
    • 支持字符串數組類型的全文檢索
    • 支持英文、中文以及Unicode多語言分詞
  • 加速普通等值、范圍查詢,覆蓋bitmap索引的功能,未來會代替bitmap索引
    • 支持字符串、數值、日期時間類型的 =, !=, >, >=, <, <= 快速過濾
    • 支持字符串、數字、日期時間數組類型的 =, !=, >, >=, <, <=
  • 支持完善的邏輯組合
    • 新增索引對OR NOT邏輯的下推
    • 支持多個條件的任意AND OR NOT組合
  • 靈活、快速的索引管理
    • 支持在創建表上定義倒排索引
    • 支持在已有的表上增加倒排索引,而且支持增量構建倒排索引,無需重寫表中的已有數據
    • 支持刪除已有表上的倒排索引,無需重寫表中的已有數據

2.7.2 使用

CREATE TABLE table_name
(
  columns_difinition,
  INDEX idx_name1(column_name1) USING INVERTED [PROPERTIES("parser" = "english|unicode|chinese")] [COMMENT 'your comment']
  INDEX idx_name2(column_name2) USING INVERTED [PROPERTIES("parser" = "english|unicode|chinese")] [COMMENT 'your comment']
  INDEX idx_name3(column_name3) USING INVERTED [PROPERTIES("parser" = "chinese", "parser_mode" = "fine_grained|coarse_grained")] [COMMENT 'your comment']
  INDEX idx_name4(column_name4) USING INVERTED [PROPERTIES("parser" = "english|unicode|chinese", "support_phrase" = "true|false")] [COMMENT 'your comment']
)
  table_properties;

 

  • 利用倒排索引加速查詢
-- 1. 全文檢索關鍵詞匹配,通過MATCH_ANY MATCH_ALL完成
SELECT * FROM table_name WHERE column_name MATCH_ANY | MATCH_ALL 'keyword1 ...';

-- 1.1 logmsg中包含keyword1的行
SELECT * FROM table_name WHERE logmsg MATCH_ANY 'keyword1';

-- 1.2 logmsg中包含keyword1或者keyword2的行,后面還可以添加多個keyword
SELECT * FROM table_name WHERE logmsg MATCH_ANY 'keyword1 keyword2';

-- 1.3 logmsg中同時包含keyword1和keyword2的行,后面還可以添加多個keyword
SELECT * FROM table_name WHERE logmsg MATCH_ALL 'keyword1 keyword2';

-- 1.4 logmsg中同時包含keyword1和keyword2的行,并且按照keyword1在前,keyword2在后的順序
SELECT * FROM table_name WHERE logmsg MATCH_PHRASE 'keyword1 keyword2';


-- 2. 普通等值、范圍、IN、NOT IN,正常的SQL語句即可,例如
SELECT * FROM table_name WHERE id = 123;
SELECT * FROM table_name WHERE ts > '2023-01-01 00:00:00';
SELECT * FROM table_name WHERE op_type IN ('add', 'delete');

 

2.8參考文檔(dang)

doris官方(fang)文檔

//doris.apache.org/zh-CN/

百(bai)度開發者中(zhong)心

//developer.baidu.com/article/detail.html?id=293810

csdn

0條評論
0 / 1000
yx_knight
5文章數
0粉絲數
yx_knight
5 文章 | 0 粉絲(si)
原創

doris索引原理及使用場景

2023-07-26 01:33:49
375
0

1.概述

索(suo)引和底(di)層存(cun)儲(chu)息息相(xiang)關,doris采用LSM的(de)存(cun)儲(chu)結(jie)構,數(shu)據(ju)(ju)首先會(hui)寫入Tablet對應(ying)的(de)memtable中,memtable寫滿之后(hou),數(shu)據(ju)(ju)會(hui)flush寫入磁(ci)盤,形成一個(ge)個(ge)不可變的(de)segment文件(jian), 由于memtable用的(de)是(shi)skiplist數(shu)據(ju)(ju)結(jie)構,skiplist數(shu)據(ju)(ju)是(shi)按照key排序的(de),所以flush到磁(ci)盤的(de)segment文件(jian)也是(shi)按照key排序的(de),doris底(di)層是(shi)按照列存(cun)儲(chu)數(shu)據(ju)(ju)的(de),存(cun)儲(chu)在(zai)一種(zhong)SST的(de)數(shu)據(ju)(ju)結(jie)構中,每(mei)列數(shu)據(ju)(ju)會(hui)被(bei)分為多(duo)個(ge)data page。

數據(ju)從(cong)memtable flush到磁盤分為兩(liang)個階段(duan):

 1.將memtable中的行(xing)存結構(gou)轉(zhuan)換(huan)為(wei)列存結構(gou),并為(wei)每(mei)一列生成對應的索引結構(gou)

 2.將(jiang)轉換后的列存結構寫入磁(ci)盤(pan),生(sheng)成segment文(wen)件。

segment文件分(fen)為數據區域、索(suo)引區域和footer三個部分(fen),如下圖所示:

說明:

data region: 存儲各個列(lie)(lie)的數據(ju)信息,每列(lie)(lie)數據(ju)被(bei)分(fen)為多個data page。

index region: Doris 中(zhong)將各(ge)個列(lie)的 index 數(shu)據(ju)統一存(cun)儲在 Index Region,這里的數(shu)據(ju)會按(an)照列(lie)粒度進行(xing)加載,所(suo)以跟(gen)列(lie)的數(shu)據(ju)信息分開存(cun)儲

footer信息

footer信息段在文件的(de)尾(wei)部(bu),存儲了文件的(de)整(zheng)體(ti)結構,包括數據域和索引域的(de)位置等,共(gong)分(fen)(fen)為SegmentFooterPB,CheckSum,Length,MAGIC CODE 4 個部(bu)分(fen)(fen)。

segementFooterPB定義(yi)了元數(shu)據信息,包括列的元數(shu)據信息,索(suo)引的元數(shu)據信息,前綴索(suo)引信息,總行(xing)數(shu)等,數(shu)據結構如下:

 

2.索引

目(mu)前 Doris 主要(yao)支(zhi)持兩類索引:

  1. 內建的智能索引,包括前綴索引和 ZoneMap 索引。
  2. 用戶手動創建的二級索引,包括 倒排索引、 bloomfilter索引、 ngram bloomfilter索引 和bitmap索引

2.1前綴索引

Doris 不支持在任意列上創建索引。Doris 這類(lei) MPP 架構的 OLAP 數(shu)據庫,通常都是通過提高并發(fa),來處理大量數(shu)據的。

本質上(shang),Doris 的數(shu)據(ju)存儲在類(lei)似 SSTable(Sorted String Table)的數(shu)據(ju)結構(gou)中。該(gai)結構(gou)是一種有序的數(shu)據(ju)結構(gou),可(ke)以按照指定的列進(jin)行(xing)排(pai)序存儲。在這種數(shu)據(ju)結構(gou)上(shang),以排(pai)序列作為(wei)條件進(jin)行(xing)查找,會非常的高效(xiao)。

在 Aggregate、Unique 和(he) Duplicate 三種(zhong)數據模型(xing)中。底層的數據存儲,是按照(zhao)各自建表語句中,AGGREGATE KEY、UNIQUE KEY 和(he) DUPLICATE KEY 中指定的列進(jin)行排序存儲的。

而前(qian)(qian)綴(zhui)索(suo)引(yin),即在排序的基礎上,實現的一(yi)種根據給定前(qian)(qian)綴(zhui)列(lie),快速(su)查詢(xun)數據的索(suo)引(yin)方式。前(qian)(qian)綴(zhui)索(suo)引(yin)又叫Short Key Index。

2.1.1存儲結構

前綴(zhui)索引是一(yi)種稀疏索引,數據(ju)寫入過程中,每隔(ge)(ge)1024行會(hui)生成(cheng)一(yi)個索引項,前綴(zhui)索引會(hui)對每一(yi)個索引間隔(ge)(ge)的(de)(de)第一(yi)個數據(ju)行的(de)(de)前綴(zhui)字段(duan)進行編(bian)碼,前綴(zhui)字段(duan)的(de)(de)編(bian)碼與前綴(zhui)字段(duan)的(de)(de)值具有相(xiang)同的(de)(de)排(pai)序(xu)(xu)規(gui)則,即前綴(zhui)字段(duan)的(de)(de)值排(pai)序(xu)(xu)越(yue)靠前,對應(ying)的(de)(de)編(bian)碼值排(pai)序(xu)(xu)也(ye)越(yue)靠前。Segment 文(wen)件是按 Key 排(pai)序(xu)(xu)的(de)(de),因此,前綴(zhui)索引項也(ye)是按 Key 排(pai)序(xu)(xu)的(de)(de)。

一個 Segment 文件中的前綴索引數據保存在一個獨立的 Short Key Page 中,其中包含每一條前綴索引項的編碼數據、每一條前綴索引項的 offset、Short Key Page 的 footer 以及 Short Key Page 的 Checksum 信息。Short Key Page 的 footer 中記錄了 Page 的類型、前綴索引編碼數據的大小、前綴索引 offset 數據的大小、前綴索引項的數目等信息

Short Key Page 在 Segment 中的 offset 和大小會被保存在Segment文件的footer中,以便于數據讀取(qu)時能夠正確地從Segment文件中加載(zai)出前(qian)綴索引數據。前(qian)綴索引的存儲結構如圖(tu)所示(shi):

 

查(cha)詢時會先(xian)打開segment文(wen)件,然后在segment footer中找(zhao)到short key page的(de)offset及大小,然后讀(du)取(qu)對應的(de)short key page中索引(yin)數(shu)據(ju),并(bing)解析(xi)每一條(tiao)前綴(zhui)索引(yin)項。

2.1.2索引生成規則

doris將一行數據的前36個字節作(zuo)為前綴索(suo)引(yin),如果遇(yu)到(dao)varchar類型,前綴索(suo)引(yin)會直接截斷(duan),

2.1.3應用案例

  1. 以下表結構(gou)的前(qian)綴索引(yin)為(wei) user_id(8 Bytes) + age(4 Bytes) + message(prefix 20 Bytes)。

    ColumnName Type
    user_id BIGINT
    age INT
    message VARCHAR(100)
    max_dwell_time DATETIME
    min_dwell_time DATETIME
  2. 以下表結構(gou)的前(qian)綴索(suo)引為 user_name(20 Bytes)。即(ji)使沒(mei)有達到 36 個字(zi)節,因為遇到 VARCHAR,所以直(zhi)接截斷,不(bu)再往(wang)后繼續。

    ColumnName Type
    user_name VARCHAR(20)
    age INT
    message VARCHAR(100)
    max_dwell_time DATETIME
    min_dwell_time DATETIME

當我們的查詢條件,是前綴索引的前綴時,可以極大的(de)加快查(cha)詢速(su)度。比如在(zai)第一個例子中,我們執行如下查(cha)詢:

SELECT * FROM table WHERE user_id=1829239 and age=20;
 

該查詢的效率會遠高于如下查詢:

SELECT * FROM table WHERE age=20;
 

所以在建表時,正確的選擇列順序,能夠極大地提高查詢效率

 

2.2 Zone Map 索引

segment中(zhong)的每列(lie)數(shu)據和(he)列(lie)中(zhong)的每個(ge)data page也會(hui)(hui)有(you)zone map索引項,zone map索引記錄每列(lie)及列(lie)中(zhong)每個(ge)data page的最(zui)大值(zhi)(zhi)(zhi)(zhi)(max value)最(zui)小值(zhi)(zhi)(zhi)(zhi)(min value),是否(fou)有(you)Null值(zhi)(zhi)(zhi)(zhi)(has null),是否(fou)有(you)非Null值(zhi)(zhi)(zhi)(zhi)(has not null)等信息。初始化時(shi)(shi)(數(shu)據為空時(shi)(shi)),max value會(hui)(hui)被設(she)置(zhi)為當前(qian)列(lie)類(lei)型的最(zui)小值(zhi)(zhi)(zhi)(zhi), min value會(hui)(hui)被設(she)置(zhi)為當前(qian)列(lie)類(lei)型的最(zui)大值(zhi)(zhi)(zhi)(zhi),has null和(he)has not null均(jun)為false.

2.2.1索引生成規則

doris默認為key列(AGGREGATE KEY、UNIQ KEY 和 DUPLICATE KEY)開(kai)啟ZoneMap索引(yin),當表模型(xing)為 DUPULCATE 時(shi),所有字段會開(kai)啟 ZoneMap 索引(yin)。

數據寫入時(shi),會給data page生成zone map索引,當data page中有(you)數據更新時(shi),對應的zone map索引也(ye)要更新。更新規則如下:

 1.如果新增(zeng)的數據為null, 則has null=true, 否則has not null=true

 2.如果新增數據(ju)小(xiao)于zone map索引中(zhong)的(de)min value,則使用當前(qian)數據(ju)更新min value, 如果新增數據(ju)大于zone map索引中(zhong)的(de)max value,則使用當前(qian)數據(ju)更新max value.

當一個Data Page寫滿之后,不僅會更新當前data page的zone map索引,也會更新data page所在列的索引。

2.2.2 應用

在查詢(xun)過程中(zhong),范(fan)圍(wei)條件(jian)過濾(lv)字段會根據zone map索引中(zhong)的統(tong)計信息選取掃描的數據范(fan)圍(wei)。

查詢如下:

SELECT * FROM table WHERE age > 20 and age < 1000

在沒有命中 Short Key Index 的(de)情(qing)況下,會(hui)根(gen)據條(tiao)件語句中 age 的(de)查詢條(tiao)件,利用 ZoneMap 索引找到應該掃(sao)描的(de)數(shu)據 ordinary 范圍,減少要掃(sao)描的(de) page 數(shu)量。

 

2.3 Ordinal 索引

2.3.1索引生成規則

Doris 底層采用列(lie)存的方式來存儲(chu)數據,每一(yi)列(lie)數據會被分(fen)為多個(ge)Data Page。

數(shu)據刷寫時,會(hui)為每一(yi)個Data Page生成一(yi)條Ordinal索引(yin)(yin)項,該(gai)索引(yin)(yin)項保(bao)(bao)存(cun)Data Page在(zai)Segment文(wen)件中(zhong)的(de)(de)offset、Data Page的(de)(de)大小以(yi)及(ji)Data Page的(de)(de)起(qi)始(shi)行號,所有(you)Data Page的(de)(de)Ordinal索引(yin)(yin)項會(hui)保(bao)(bao)存(cun)在(zai)一(yi)個Ordinal Index Page中(zhong), Ordinal Index Page在(zai)Segment文(wen)件中(zhong)的(de)(de)offset以(yi)及(ji)Ordinal Index Page的(de)(de)大小會(hui)被(bei)保(bao)(bao)存(cun)在(zai)Segment文(wen)件的(de)(de)footer中(zhong),以(yi)便于數(shu)據讀取(qu)時能夠通(tong)過兩(liang)級(ji)索引(yin)(yin)找(zhao)到(dao)Data Page(首先,通(tong)過Segment文(wen)件的(de)(de)footer找(zhao)到(dao)Ordinal Index Page,然后,通(tong)過Ordinal Index Page中(zhong)的(de)(de)索引(yin)(yin)項找(zhao)到(dao)Data Page)。

Ordinal Index Page包含(han)以下信(xin)息:所有Ordinal索(suo)引(yin)項(xiang)數(shu)據(ju)、Ordinal Index Page的footer以及Short Key Page的Checksum信(xin)息。Ordinal Index Page的footer中包含(han)當前Page的類型(xing)、Ordinal索(suo)引(yin)項(xiang)數(shu)據(ju)的大小、Ordinal索(suo)引(yin)項(xiang)數(shu)目(mu)等信(xin)息。

如(ru)(ru)果列(lie)中只有一(yi)個(ge)Data Page時(shi),即該(gai)列(lie)只有一(yi)條(tiao)Ordinal索引項,則Segment文(wen)(wen)件(jian)中不需要保存(cun)該(gai)列(lie)的(de)Ordinal索引數據,只需要將(jiang)這(zhe)唯一(yi)的(de)Data Page在Segment文(wen)(wen)件(jian)中的(de)offset以(yi)及(ji)該(gai)Data Page的(de)大(da)小保存(cun)在Segment文(wen)(wen)件(jian)的(de)footer中。數據讀取(qu)時(shi)可以(yi)通過Segment文(wen)(wen)件(jian)的(de)footer直接找(zhao)到(dao)這(zhe)唯一(yi)的(de)Data Page。Ordinal索引的(de)存(cun)儲結構如(ru)(ru)圖3所示。

Ordinal索引(yin)的作用(yong)是(shi)為了方便其他類(lei)型的索引(yin)能夠使用(yong)統一的方式查找Data Page,進而可以(yi)對(dui)其他類(lei)型的索引(yin)屏蔽Data Page在(zai)Segment文件中的offset

2.3.2查詢過濾

查詢時(shi),會加載每(mei)一(yi)個列(lie)的Ordinal索引(yin)(yin)數據。通過Segment footer中記(ji)錄的Ordinal索引(yin)(yin)的Meta信息判斷當前列(lie)是否存在(zai)Ordinal Index Page,即判斷當前列(lie)是否有(you)多個Data Page。

如果當(dang)前列存在(zai)Ordinal Index Page,則從Segment footer中(zhong)獲取(qu)Ordinal Index Page在(zai)Segment中(zhong)的(de)(de)(de)offset和Ordinal Index Page的(de)(de)(de)大(da)小,然后從Segment文件中(zhong)讀取(qu)Ordinal Index Page數據,并解析出每一條Ordinal索引項(xiang),即可通(tong)過Ordinal索引項(xiang)獲取(qu)當(dang)前列中(zhong)每一個Data Page的(de)(de)(de)起(qi)始行號、Data Page在(zai)Segment中(zhong)的(de)(de)(de)offset以及Data Page的(de)(de)(de)大(da)小。

如果當(dang)前(qian)列不存在Ordinal Index Page,則可以直接(jie)從Segment footer中(zhong)獲取當(dang)前(qian)列中(zhong)唯一的Data Page在Segment中(zhong)的offset以及Data Page的大(da)小。

 

2.4 BitMap索引

為了加速查詢,doris支(zhi)持用(yong)戶為字段創建Bitmap索引(yin),Bitmap索引(yin)由兩部(bu)分組成(cheng):

  1.有序字典(dian):有序保(bao)存一列中所有的(de)不(bu)同(tong)取值。

  2.字(zi)典(dian)的位圖:保存有序字(zi)典(dian)中每一個值(zhi)的位圖,值(zhi)是字(zi)典(dian)值(zhi)在列中的行(xing)號。

一(yi)列(lie)數據為(wei)[x, x, y, y, y, z, y, x, z, x],一(yi)共包含10行(xing),則該列(lie)數據的(de)Bitmap索引的(de)有序字典為(wei){x, y, z}, 其中x、y、z對應的(de)位(wei)圖分別為(wei):

x的位圖(tu): [0, 1, 7, 9]

y的位圖(tu): [2, 3, 4, 6]

z的(de)位圖: [5, 8]

如下圖所示:

左側為(wei)(wei)有序字典,右側為(wei)(wei)字典每一(yi)個元(yuan)素(su)對(dui)應的(de)位圖。

 

2.4.1 索引生成規則

數據刷(shua)寫時(shi),會(hui)給用戶(hu)指(zhi)定的列創建Bitmap索引(yin)(yin)。向列中每添(tian)加一個值,都會(hui)更(geng)新(xin)當前列的BitMap索引(yin)(yin)。從Bitmap索引(yin)(yin)對應(ying)的有序(xu)字(zi)典(dian)查找新(xin)添(tian)加的值是否(fou)存(cun)在,如果(guo)已經存(cun)在,則只(zhi)更(geng)新(xin)該字(zi)典(dian)值對應(ying)的位圖;如果(guo)不存(cun)在,則將該值添(tian)加到有序(xu)字(zi)典(dian)中,并(bing)為這個值生(sheng)(sheng)成位圖,Null值也(ye)會(hui)有單(dan)獨(du)的位圖。可以(yi)看出Bitmap只(zhi)適合低(di)基(ji)數的列,如果(guo)基(ji)數很高,生(sheng)(sheng)成大(da)(da)量的位圖會(hui)占用巨(ju)大(da)(da)的空間。

Bitmap索引的字典數(shu)據(ju)和位圖(tu)數(shu)據(ju)分開存儲(chu)。

字(zi)典(dian)數據存(cun)儲(chu)在(zai)對應(ying)的(de)(de)dict page中(zhong)(zhong),位(wei)圖(tu)數據存(cun)儲(chu)在(zai)對應(ying)的(de)(de)Bitmap page中(zhong)(zhong),而dict page和Bitmap page的(de)(de)元信息會(hui)記錄在(zai)segment footer中(zhong)(zhong)。如果一(yi)(yi)(yi)個(ge)(ge)列(lie)有多個(ge)(ge)dict page則(ze)會(hui)轉化成兩級索(suo)引(yin)(yin)(yin),第(di)二級索(suo)引(yin)(yin)(yin)為(wei)多個(ge)(ge)dict page,保存(cun)字(zi)典(dian)數據,每一(yi)(yi)(yi)個(ge)(ge)dict page生成一(yi)(yi)(yi)條(tiao)value索(suo)引(yin)(yin)(yin)項,所有dict page的(de)(de)value 索(suo)引(yin)(yin)(yin)項會(hui)被被保存(cun)在(zai)一(yi)(yi)(yi)個(ge)(ge)value index page中(zhong)(zhong)作為(wei)一(yi)(yi)(yi)級索(suo)引(yin)(yin)(yin),每一(yi)(yi)(yi)個(ge)(ge)的(de)(de)Value索(suo)引(yin)(yin)(yin)項記錄了當(dang)前(qian)Dict Page中(zhong)(zhong)第(di)一(yi)(yi)(yi)個(ge)(ge)字(zi)典(dian)值的(de)(de)編碼以及當(dang)前(qian)Dict Page在(zai)Segment文件(jian)中(zhong)(zhong)的(de)(de)offset和大小,而value index page的(de)(de)元信息則(ze)保存(cun)在(zai)segment footer中(zhong)(zhong)。

同(tong)理如果(guo)一個(ge)(ge)列有多(duo)個(ge)(ge)Bitmap page則會轉化成二(er)級索(suo)(suo)(suo)(suo)引(yin)(yin),第(di)二(er)級索(suo)(suo)(suo)(suo)引(yin)(yin)為(wei)多(duo)個(ge)(ge)的Bitmap Page,其中保(bao)存(cun)Bitmap索(suo)(suo)(suo)(suo)引(yin)(yin)的位圖數據,每一個(ge)(ge)Bitmap Page生成一條Ordinal索(suo)(suo)(suo)(suo)引(yin)(yin)項,所有Bitmap Page的Ordinal索(suo)(suo)(suo)(suo)引(yin)(yin)項會被保(bao)存(cun)在(zai)一個(ge)(ge)Ordinal Index Page(注意,此處的Ordinal 索(suo)(suo)(suo)(suo)引(yin)(yin)與第(di)3部(bu)分的Ordinal 索(suo)(suo)(suo)(suo)引(yin)(yin)不同(tong),此處的Ordinal 索(suo)(suo)(suo)(suo)引(yin)(yin)指向(xiang)(xiang)Bitmap Page,而第(di)3部(bu)分的Ordinal 索(suo)(suo)(suo)(suo)引(yin)(yin)指向(xiang)(xiang)Data Page)中作為(wei)一級索(suo)(suo)(suo)(suo)引(yin)(yin),而Ordinal Index Page的元信息(xi)則保(bao)存(cun)在(zai)segment footer中。

2.4.2適用場景

Doris支(zhi)持在建表時對指定(ding)的列創建Bitmap索(suo)(suo)引(yin)(yin),也(ye)可以對已(yi)經創建的表執行Alter Table命令(ling)添加Bitmap索(suo)(suo)引(yin)(yin)。

ALTER TABLE table_name ADD INDEX index_name (column_name) USING BITMAP COMMENT ‘’;

目前只支持(chi)對TINYINT、SMALLINT、INT、 UNSIGNEDINT、BIGINT、LARGEINT、CHAR、 VARCHAR、DATE、DATETIME、BOOL和DECIMAL類(lei)型的字(zi)段(duan)創(chuang)建Bitmap索引,其他類(lei)型的字(zi)段(duan)均(jun)不支持(chi)Bitmap索引。

Bitmap索引比較(jiao)適合在基數較(jiao)低的列上(shang)進行等(deng)值(zhi)查(cha)詢或范圍查(cha)詢的場景

 

2.5 Bloom Filter索引

Bloom Filter索引(yin)按照Data Page的(de)粒度生(sheng)成。數(shu)據寫(xie)(xie)入時,會記錄(lu)每一個寫(xie)(xie)入Data Page的(de)值,當(dang)一個Data Page寫(xie)(xie)滿之(zhi)后,會根據該Data Page的(de)所有(you)不同取值為(wei)該Data Page生(sheng)成Bloom Filter索引(yin)。數(shu)據查詢時,查詢條件在設置有(you)Bloom Filter索引(yin)的(de)字段進(jin)行(xing)過(guo)濾,當(dang)某個Data Page的(de)Bloom Filter沒(mei)有(you)命中時,表示該Data Page中沒(mei)有(you)需要的(de)數(shu)據,這樣可以對Data Page進(jin)行(xing)快速(su)過(guo)濾,減少不必(bi)要的(de)數(shu)據讀取。

 

2.5.1適用場景

Doris支持在建表時對指定(ding)的(de)列創建Bloom Filter索引,也可以對已(yi)經創建的(de)表執(zhi)行Alter Table命令添加Bloom Filter索引。

ALTER TABLE table_name SET (“bloom_filter_columns”=”c1, c2, c3”);

目前(qian)只(zhi)支持(chi)(chi)對SMALLINT、INT、UNSIGNEDINT、 BIGINT、LARGEINT、CHAR、 VARCHAR、DATE、DATETIME和DECIMAL類型(xing)(xing)的(de)(de)字(zi)(zi)段創(chuang)建Bloom Filter索(suo)(suo)引(yin),其(qi)他類型(xing)(xing)的(de)(de)字(zi)(zi)段均不(bu)支持(chi)(chi)Bloom Filter索(suo)(suo)引(yin)。對于創(chuang)建了Bloom Filter索(suo)(suo)引(yin)的(de)(de)字(zi)(zi)段,查(cha)詢條件是”=”、”is”或”in”語(yu)句時(shi),才會使(shi)用Bloom Filter索(suo)(suo)引(yin)進行Data Page的(de)(de)過濾。Bloom Filter索(suo)(suo)引(yin)比較(jiao)適(shi)合在(zai)基數較(jiao)高的(de)(de)列上(shang)進行等(deng)值(zhi)查(cha)詢的(de)(de)場景。

 

2.6NGram BloomFilter索引

為了提升like的查詢性(xing)能(neng),增加(jia)了NGram BloomFilter索引(yin)。

2.6.1 NGram BloomFilter創建?

表創建時指定:

CREATE TABLE `table3` (
`siteid` int(11) NULL DEFAULT "10" COMMENT "",
`citycode` smallint(6) NULL COMMENT "",
`username` varchar(32) NULL DEFAULT "" COMMENT "",
INDEX idx_ngrambf (`username`) USING NGRAM_BF PROPERTIES("gram_size"="3", "bf_size"="256") COMMENT 'username ngram_bf index'
) ENGINE=OLAP
AGGREGATE KEY(`siteid`, `citycode`, `username`) COMMENT "OLAP"
DISTRIBUTED BY HASH(`siteid`) BUCKETS 10
PROPERTIES (
"replication_num" = "1"
);

-- PROPERTIES("gram_size"="3", "bf_size"="256"),分別(bie)表(biao)示gram的(de)個數(shu)和bloom filter的(de)字節數(shu)。
-- gram的個數跟實際查詢場(chang)景相關(guan),通常設置為大(da)部分(fen)查詢字符串的長度,bloom filter字節數,可以(yi)通過(guo)測試(shi)得出,通常越大(da)過(guo)濾效果越好,可以(yi)從256開始進行驗證測試(shi)看(kan)(kan)看(kan)(kan)效果。當然字節數越大(da)也會帶來索引存儲、內存cost上升(sheng)。
-- 如果數(shu)據基數(shu)比較高(gao),字(zi)節數(shu)可以(yi)不用(yong)設置過(guo)大,如果基數(shu)不是(shi)很高(gao),可以(yi)通過(guo)增(zeng)加字(zi)節數(shu)來提升過(guo)濾效果。

2.6.2 NGram BloomFilter使用注意事項?

  1. NGram BloomFilter只支持字符串列
  2. NGram BloomFilter索引和BloomFilter索引為互斥關系,即同一個列只能設置兩者中的一個
  3. NGram大小和BloomFilter的字節數,可以根據實際情況調優,如果NGram比較小,可以適當增加BloomFilter大小
  4. 如果要查看某個查詢是否命中了NGram Bloom Filter索引,可以通過查詢的Profile信息查看

 

2.7 倒排索引

從(cong)2.0.0版本(ben)開始(shi),Doris支(zhi)持倒(dao)排索(suo)引(yin),可以用來進行文本(ben)類型的全(quan)文檢索(suo)、普通(tong)數(shu)值日期類型的等值范圍(wei)查詢,快速從(cong)海量數(shu)據中過濾出滿足條件的行。本(ben)文檔主要(yao)介紹(shao)如何倒(dao)排索(suo)引(yin)的創建、刪除、查詢等使用方式。

inverted index倒排索引,是信息檢索(suo)領域常用(yong)的索(suo)引(yin)技術,將文(wen)(wen)本分割成一(yi)(yi)個個詞(ci)(ci),構建(jian) 詞(ci)(ci) -> 文(wen)(wen)檔(dang)編(bian)號 的索(suo)引(yin),可以(yi)快(kuai)速查找一(yi)(yi)個詞(ci)(ci)在哪些文(wen)(wen)檔(dang)出現。

在Doris的倒排(pai)索引實(shi)現中(zhong),table的一行對(dui)應一個文檔、一列對(dui)應文檔中(zhong)的一個字段(duan),因(yin)此利用倒排(pai)索引可以根據(ju)關(guan)鍵詞快速(su)定(ding)位包(bao)含它(ta)的行,達(da)到WHERE子句加速(su)的目的。

與(yu)Doris中其(qi)他(ta)索引(yin)不同的(de)是,在存儲層(ceng)倒排索引(yin)使(shi)用獨立的(de)文件,跟(gen)segment文件有邏輯對應關系、但(dan)存儲的(de)文件相(xiang)互獨立。這樣(yang)的(de)好(hao)處是可以做到(dao)創建、刪除索引(yin)不用重寫tablet和segment文件,大(da)幅降低處理開銷。

 

2.7.1 功能

  • 增加了字符串類型的全文檢索
    • 支持字符串全文檢索,包括同時匹配多個關鍵字MATCH_ALL、匹配任意一個關鍵字MATCH_ANY、匹配短語詞組MATCH_PHRASE
    • 支持字符串數組類型的全文檢索
    • 支持英文、中文以及Unicode多語言分詞
  • 加速普通等值、范圍查詢,覆蓋bitmap索引的功能,未來會代替bitmap索引
    • 支持字符串、數值、日期時間類型的 =, !=, >, >=, <, <= 快速過濾
    • 支持字符串、數字、日期時間數組類型的 =, !=, >, >=, <, <=
  • 支持完善的邏輯組合
    • 新增索引對OR NOT邏輯的下推
    • 支持多個條件的任意AND OR NOT組合
  • 靈活、快速的索引管理
    • 支持在創建表上定義倒排索引
    • 支持在已有的表上增加倒排索引,而且支持增量構建倒排索引,無需重寫表中的已有數據
    • 支持刪除已有表上的倒排索引,無需重寫表中的已有數據

2.7.2 使用

CREATE TABLE table_name
(
  columns_difinition,
  INDEX idx_name1(column_name1) USING INVERTED [PROPERTIES("parser" = "english|unicode|chinese")] [COMMENT 'your comment']
  INDEX idx_name2(column_name2) USING INVERTED [PROPERTIES("parser" = "english|unicode|chinese")] [COMMENT 'your comment']
  INDEX idx_name3(column_name3) USING INVERTED [PROPERTIES("parser" = "chinese", "parser_mode" = "fine_grained|coarse_grained")] [COMMENT 'your comment']
  INDEX idx_name4(column_name4) USING INVERTED [PROPERTIES("parser" = "english|unicode|chinese", "support_phrase" = "true|false")] [COMMENT 'your comment']
)
  table_properties;

 

  • 利用倒排索引加速查詢
-- 1. 全文檢索關鍵詞匹配,通過MATCH_ANY MATCH_ALL完成
SELECT * FROM table_name WHERE column_name MATCH_ANY | MATCH_ALL 'keyword1 ...';

-- 1.1 logmsg中包含keyword1的行
SELECT * FROM table_name WHERE logmsg MATCH_ANY 'keyword1';

-- 1.2 logmsg中包含keyword1或者keyword2的行,后面還可以添加多個keyword
SELECT * FROM table_name WHERE logmsg MATCH_ANY 'keyword1 keyword2';

-- 1.3 logmsg中同時包含keyword1和keyword2的行,后面還可以添加多個keyword
SELECT * FROM table_name WHERE logmsg MATCH_ALL 'keyword1 keyword2';

-- 1.4 logmsg中同時包含keyword1和keyword2的行,并且按照keyword1在前,keyword2在后的順序
SELECT * FROM table_name WHERE logmsg MATCH_PHRASE 'keyword1 keyword2';


-- 2. 普通等值、范圍、IN、NOT IN,正常的SQL語句即可,例如
SELECT * FROM table_name WHERE id = 123;
SELECT * FROM table_name WHERE ts > '2023-01-01 00:00:00';
SELECT * FROM table_name WHERE op_type IN ('add', 'delete');

 

2.8參考文檔

doris官方文檔

//doris.apache.org/zh-CN/

百度開發者(zhe)中心(xin)

//developer.baidu.com/article/detail.html?id=293810

csdn

文章來自個人專欄
文章 | 訂閱
0條評論
0 / 1000
請輸入你的評論
0
0