半結(jié)構(gòu)化分析主要是指對(duì) MAP,STRUCT,JSON,ARRAY 等復(fù)雜數(shù)據(jù)類(lèi)型的查詢(xún)分析。這些數(shù)據(jù)類(lèi)型表達(dá)能力強(qiáng),因此被廣泛應(yīng)用到 OLAP 分析的各種場(chǎng)景中,但由于其實(shí)現(xiàn)的復(fù)雜性,對(duì)這些復(fù)雜類(lèi)型分析將會(huì)比一般簡(jiǎn)單類(lèi)型要更困難和耗時(shí),例如:
-
需要對(duì) MAP,STRUCT,JSON 等數(shù)據(jù)類(lèi)型中的某個(gè)字段進(jìn)行查詢(xún)分析。由于這些復(fù)雜類(lèi)型會(huì)被存儲(chǔ)為一個(gè)整體,因此需要先將整個(gè)半結(jié)構(gòu)化類(lèi)型的字段先從存儲(chǔ)層讀取上來(lái),然后再對(duì)其中的某些字段進(jìn)行分析,IO效率較低。 -
對(duì)復(fù)雜類(lèi)型進(jìn)行較為耗時(shí)的分析計(jì)算(聚合,排序等等),查詢(xún)的實(shí)時(shí)CPU 開(kāi)銷(xiāo)可能也是一個(gè)不可忽略的性能影響因素。
面對(duì)上述的挑戰(zhàn),StarRocks在3.1 版本正式推出生成列(Generated Column)特性,提供一種透明加速的解決方案,能有效提升半結(jié)構(gòu)化數(shù)據(jù)的分析效率,令用戶(hù)擁有更極速的分析體驗(yàn)。
生成列介紹
生成列是一種特殊的列,可以在建表語(yǔ)句或 Schema Change 語(yǔ)句中指定,生成列綁定到一個(gè)標(biāo)量表達(dá)式上,當(dāng)數(shù)據(jù)導(dǎo)入時(shí),會(huì)自動(dòng)根據(jù)表達(dá)式定義進(jìn)行計(jì)算,并且將其計(jì)算結(jié)果寫(xiě)入到生成列中。

在半結(jié)構(gòu)化分析的場(chǎng)景中,可以將復(fù)雜耗時(shí)的標(biāo)量表達(dá)式綁定在某個(gè)生成列上,在數(shù)據(jù)導(dǎo)入階段提前將結(jié)果計(jì)算好并且持久化到磁盤(pán)中。當(dāng)需要進(jìn)行查詢(xún)分析時(shí),即可馬上獲得表達(dá)式計(jì)算的結(jié)果。
生成列的查詢(xún)改寫(xiě)
當(dāng)希望查詢(xún)生成列保存的表達(dá)式計(jì)算結(jié)果時(shí),可以直接在 SQL 中指定生成列的列名,但是這種方法意味著需要調(diào)整已有業(yè)務(wù) SQL,很難完全做到無(wú)縫對(duì)接。
為了進(jìn)一步提升功能的使用體驗(yàn),簡(jiǎn)化使用流程,StarRocks 支持生成列自動(dòng)查詢(xún)改寫(xiě)。在生成執(zhí)行計(jì)劃時(shí),SQL 優(yōu)化器將會(huì)檢查 SQL 中所有的表達(dá)式,并且將那些已經(jīng)綁定到生成列上的表達(dá)式,改寫(xiě)成查詢(xún)生成列列值。
例如,上述例子中,如果在某個(gè)查詢(xún)中需要獲取 colc 中的 a 字段,則執(zhí)行查詢(xún)SELECT get_json_string(json_string(tbl.colc), '$.a') FROM tbl,執(zhí)行過(guò)程大致如下:

可見(jiàn),優(yōu)化器自動(dòng)將表達(dá)式改寫(xiě)為查詢(xún)生成列的值,實(shí)現(xiàn)透明加速。
高效的生成列加列
在實(shí)際應(yīng)用生成列的使用場(chǎng)景中,在已有的表添加生成列可能是一個(gè)高頻操作。例如,可能在任意時(shí)間點(diǎn)發(fā)現(xiàn)某個(gè)表達(dá)式計(jì)算存在性能瓶頸,因此希望添加生成列以進(jìn)行查詢(xún)加速。
StarRocks 支持高效的加列操作,對(duì)于添加普通列,存儲(chǔ)引擎并不會(huì)真正重寫(xiě)物理文件,而只是將物理文件重新 link 到新 Tablet 的路徑下,修改元數(shù)據(jù),完成加列操作。但是,如 MODIFY COLUMN 這類(lèi) Schema Change 操作,由于需要改變存量數(shù)據(jù)的內(nèi)容,因此會(huì)重寫(xiě)所有物理文件。類(lèi)似地,對(duì)于生成列加列來(lái)說(shuō),由于需要存儲(chǔ)新增的生成列表達(dá)式的計(jì)算結(jié)果,重寫(xiě)數(shù)據(jù)似乎也是不可避免的。但是,如果仍然采用全量重寫(xiě)物理文件的方案,將無(wú)法很好適應(yīng)頻繁加列的場(chǎng)景,加列的代價(jià)太大。
為了進(jìn)一步提高生成列加列的效率,StarRocks 針對(duì)生成列加列進(jìn)行了專(zhuān)門(mén)的優(yōu)化。當(dāng)添加一個(gè)生成列時(shí),不會(huì)改寫(xiě)存量的物理文件,而是為每一個(gè)存量的 segment 生成一個(gè)只包含生成列值的 cols 文件(物理格式和 segment 文件一樣,但只包含生成列一列數(shù)據(jù)),當(dāng)需要查詢(xún)這些存量數(shù)據(jù)時(shí),StarRocks 會(huì)自動(dòng)將 segment 和 cols 文件的內(nèi)容進(jìn)行合并,獲得正確的查詢(xún)結(jié)果。
總的來(lái)說(shuō),生成列加列優(yōu)化后,讀 I/O 只涉及到生成列表達(dá)式的引用列,寫(xiě) I/O 只涉及到生成列本身的表達(dá)式結(jié)果,整個(gè) Schema Change 的 I/O 效率相比完全重寫(xiě)有大幅提高,更好支持實(shí)時(shí)動(dòng)態(tài)生成列加列的用戶(hù)需求。

效果驗(yàn)證
為了更好驗(yàn)證生成列對(duì)半結(jié)構(gòu)化分析的加速效果,我們進(jìn)行了簡(jiǎn)單的測(cè)試驗(yàn)證。
集群信息:StarRocks v3.1 1FE1BE ,104C376GB
創(chuàng)建一張如下的數(shù)據(jù)表,
CREATE?TABLE?`t`?(
??`id`?bigint(20)?NOT?NULL?COMMENT?"",
??`array_int`?ARRAY<int(11)>?NOT?NULL?COMMENT?"",
??`json_data`?json?NOT?NULL?COMMENT?"",
??`gc_1`?double?NULL?AS?array_avg(`test`.`t`.`array_int`)?COMMENT?"",
??`gc_2`?ARRAY<int(11)>?NULL?AS?array_sort(`test`.`t`.`array_int`)?COMMENT?"",
??`gc_3`?varchar(65533)?NULL?AS?get_json_string(json_string(`test`.`t`.`json_data`),?'$.a')?COMMENT?""
)?ENGINE=OLAP?
PRIMARY?KEY(`id`)
COMMENT?"OLAP"
DISTRIBUTED?BY?HASH(`id`)?BUCKETS?48?
PROPERTIES?(
"replication_num"?=?"1",
"in_memory"?=?"false",
"storage_format"?=?"DEFAULT",
"enable_persistent_index"?=?"false",
"replicated_storage"?=?"true",
"compression"?=?"LZ4"
)
普通列數(shù)據(jù)創(chuàng)建方式: id,作為 primary key 列保證唯一。
array_int,長(zhǎng)度為 10000 的 ARRAY ,保存的都是隨機(jī)數(shù)。
json_data,包含兩個(gè) key,key "a" 對(duì)應(yīng)的 value 為整型 1,key "b" 對(duì)應(yīng)的value 是長(zhǎng)度為 100 個(gè) uuid 構(gòu)成的字符串 性能測(cè)試使用下面的 query:
q1:SELECT?get_json_string(json_string(json_data),?'$.a')?FROM?A
q2:SELECT?array_avg(array_int)?FROM?A;
測(cè)試結(jié)果:

從上述的測(cè)試結(jié)果可知:
q1:使用生成列提取大 JSON 字段中的某個(gè)子字段,在查詢(xún)階段大幅節(jié)省了讀取 JSON 字段的 I/O 消耗,查詢(xún)性能提升達(dá) 4 倍以上。
q2:使用生成列對(duì)大 ARRAY 字段進(jìn)行聚合計(jì)算(計(jì)算平均值),在查詢(xún)階段不僅節(jié)省讀取該半結(jié)構(gòu)化數(shù)據(jù)字段的 I/O 消耗,同時(shí)也大幅節(jié)省了 ARRAY 聚合計(jì)算所帶來(lái)的 CPU 消耗,獲得百倍的性能提升。
總結(jié)
生成列功能是一種加速半結(jié)構(gòu)化分析的有效手段,當(dāng)面對(duì)復(fù)雜的半結(jié)構(gòu)化表達(dá)式計(jì)算時(shí),可以為其添加對(duì)應(yīng)的生成列,在導(dǎo)入階段自動(dòng)完成表達(dá)式計(jì)算,并將結(jié)果持久化。在查詢(xún)階段通過(guò)優(yōu)化器的自動(dòng)改寫(xiě),直接從生成列中獲得表達(dá)式計(jì)算結(jié)果,避免實(shí)時(shí)的表達(dá)式計(jì)算,實(shí)現(xiàn)透明加速。 通過(guò)使用生成列,用戶(hù)能大幅減少查詢(xún)時(shí)復(fù)雜表達(dá)式的 I/O,CPU 等資源消耗,在不同的場(chǎng)景下獲得數(shù)倍甚至百倍的性能提升。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-815956.html
本文由 mdnice 多平臺(tái)發(fā)布文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-815956.html
到了這里,關(guān)于StarRocks 生成列:百倍提速半結(jié)構(gòu)化數(shù)據(jù)分析的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!