摘要:MySQL在充分利用多核計算資源方面比較欠缺,無法同時滿足在線業(yè)務(wù)和分析型業(yè)務(wù)的客戶需求,而單獨部署一套專用的分析型數(shù)據(jù)庫意味著額外的成本和復(fù)雜的數(shù)據(jù)鏈路。本次主題將介紹騰訊云數(shù)據(jù)庫為滿足此類場景而在HTAP for MySQL產(chǎn)品方面進(jìn)行的嘗試。
2023首屆云數(shù)據(jù)庫技術(shù)沙龍 MySQL x ClickHouse 專場,在杭州市海智中心成功舉辦。本次沙龍由NineData、菜根發(fā)展、良倉太炎共創(chuàng)聯(lián)合主辦。本次,騰訊TEG數(shù)據(jù)庫產(chǎn)品部高級技術(shù)專家陸洪勇,為大家分享一下《HTAP for MySQL 在騰訊云數(shù)據(jù)庫的演進(jìn)》的一些技術(shù)內(nèi)容。
本文內(nèi)容根據(jù)演講錄音以及PPT整理而成。
陸洪勇,騰訊TEG數(shù)據(jù)庫產(chǎn)品部高級技術(shù)專家,曾在 SAP 做過多年HANA數(shù)據(jù)庫內(nèi)核的設(shè)計與研發(fā),阿里云 Polardb 數(shù)據(jù)庫內(nèi)核的設(shè)計與研發(fā)。目前在騰訊云數(shù)據(jù)庫做 HTAP for MySQL 相關(guān)產(chǎn)品的設(shè)計與開發(fā)。
今天我來講一下,HTAP for MySQL 在騰訊云數(shù)據(jù)庫的演進(jìn)。主要介紹的內(nèi)容如下:首先介紹一下產(chǎn)品背景,然后會介紹產(chǎn)品的兩個重要功能,第一個是并行查詢,第二個是列存索引,這也是MySQL能力提升的最重要的兩個方面。
這個產(chǎn)品實際上是我們所提到的公有云,公有云的概念大家都比較熟悉。其中一個產(chǎn)品是 Tencent DB for MySQL,這是一個基于 MySQL 開源的托管產(chǎn)品。類似的產(chǎn)品還有阿里云的 RDS。這是一個典型的、傳統(tǒng)的 MySQL 主從復(fù)制架構(gòu),通過 binlog 進(jìn)行數(shù)據(jù)復(fù)制。每個節(jié)點都有自己的日志和數(shù)據(jù)。
另一個產(chǎn)品是我們的云原生數(shù)據(jù)庫產(chǎn)品 TDSQL-C,它有兩個基本特點:資源池化和極致彈性。在這個產(chǎn)品中,我們使用了分布式共享存儲來存儲數(shù)據(jù),而 CPU 和內(nèi)存等資源也將實現(xiàn)相應(yīng)的池化,后續(xù)我們還會陸續(xù)推出相應(yīng)的產(chǎn)品。極致彈性能力在于使用了共享存儲,所以我們每一個只讀節(jié)點,可以很容易的掛載上來。同時,共享存儲也很容易進(jìn)行擴(kuò)容和縮容,這是我們產(chǎn)品的基本背景介紹。
首先,我們通過對大量重點客戶在大盤上的分析,發(fā)現(xiàn)客戶存在兩大痛點。其中,第一個痛點極其重要,即穩(wěn)定性問題。第二個痛點是慢查詢,這是一個非常令人頭疼的事情。慢查詢的原因有很多,比如用戶沒有為某些查詢創(chuàng)建索引或者索引未命中。另一個更為普遍的原因是MySQL單核處理能力在數(shù)據(jù)量較大時的瓶頸。
針對這些問題,業(yè)界提出了幾種解決方案。第一種是提高多核處理能力,包括多節(jié)點并行查詢和MPP。第二種是提高指令執(zhí)行效率,其中一種方法是向量化執(zhí)行,包括SIMD指令,另一種方法是JIT編譯,目前在一些商業(yè)數(shù)據(jù)庫用的還比較多一點。第三種是提高信息密度,由于行存數(shù)據(jù)庫中數(shù)據(jù)之間的相似性較低,因此需要進(jìn)行一些壓縮或批量處理是比較難的,另一個解決方案是使用列式存儲。
在業(yè)界中,部署模式也存在類似的三種。其中一種是中間鍵模式,即在MySQL集群中構(gòu)建一個中間件,通過中間件進(jìn)行分布式查詢分析和并發(fā)執(zhí)行,最終的執(zhí)行片段會下壓到每一個的MySQL節(jié)點上去,這樣MySQL能夠把分析型能力能夠解決,其中阿里云Polardb-X產(chǎn)品就是比較典型的例子。另一種是專有的AP系統(tǒng),該系統(tǒng)建立在MySQL之外單獨建立一個分析型系統(tǒng),包括ClickHouse是比較好的一個方案,通過 binlog 或者其他的形式進(jìn)行日志同步,相當(dāng)于提供專用的日志分析,將正常數(shù)據(jù)或TP數(shù)據(jù)通過MySQL,分析的話就通過AP進(jìn)行處理。我們的產(chǎn)品其實是想在MySQL本身構(gòu)建并行查詢和AP能力,使用戶能夠無需感知我們的底層操作,不會對業(yè)務(wù)造成侵入,同時獲得非常大的性能提升。
首先,在上面的這個過程中,我們進(jìn)行了并行查詢的演進(jìn),而下面一排是關(guān)于列式存儲和引擎的演化。這兩個功能是獨立開發(fā)的。然后,在去年的六七月份,我們將這兩個技術(shù)融合,使得我們的公有云產(chǎn)品上,MySQL和云原生產(chǎn)品具有了并行查詢和列存框架。這樣一來,用戶可以享受到極大的執(zhí)行效率提升。
這個框架的融合之后,我們的兩個團(tuán)隊可以持續(xù)擴(kuò)展各自的能力,所以后面的擴(kuò)展很容易被整合進(jìn)這個框架里面。例如,我們在列存做的向量化處理和delta store等,都可以很容易地被吸收到這個執(zhí)行框架中。只要將這些功能合入到框架中,用戶就可以充分體驗到這些帶來的性能優(yōu)勢。
在2021年底,我們做了一個列存索引的功能,相當(dāng)于創(chuàng)建了一個 InnoDB的索引,數(shù)據(jù)可以通過異步傳輸同步到列存中,以實現(xiàn)數(shù)據(jù)及時同步。后面我們會有一個具體框架,可以看下我們是怎么做的。
首先,我們來介紹一下并行查詢, 我們舉了一個示例,從TPCH中選取了一個簡單的查詢語句進(jìn)行測試。在MySQL普通執(zhí)行下,該查詢需要約64秒的時間。而在使用并發(fā)查詢后,四個DOP、四個worker只需要16秒的時間??梢钥吹讲⑿胁樵兊男侍嵘蔷€性的,達(dá)到了四倍。這是MySQL原有的執(zhí)行計劃,我們可以看到每個worker線程都有一個sender節(jié)點,用于數(shù)據(jù)發(fā)送。最終數(shù)據(jù)會在gather層進(jìn)行匯總。這是一個典型的并行執(zhí)行計劃。下面是并發(fā)查詢的狀態(tài),可以通過 show process 進(jìn)行查看。
這里我們介紹一個具體的實現(xiàn)方案。在MySQL中,有一個比較困難的方案需要計劃切分,這是因為在傳統(tǒng)的數(shù)據(jù)庫中,如我之前從事的HANA數(shù)據(jù)庫,生成的計劃與數(shù)據(jù)是分離的,因此plan在傳輸?shù)狡渌鹷orker線程時很容易實現(xiàn)。但是MySQL是比較難的,主要在于傳統(tǒng)開發(fā)模式導(dǎo)致了計劃和數(shù)據(jù)的耦合,使得直接進(jìn)行plan拷貝非常困難。后面我們簡單介紹下包括業(yè)界常用的三種方案。然后我們看一下這樣簡單的一個plan,舉個例子,比如我們table scan上有一個聚合數(shù)據(jù)的表,經(jīng)過計劃切分后,我們會在worker線程上添加一個并行執(zhí)行的節(jié)點,然后再上層添加一個receiver節(jié)點來匯聚結(jié)果。如果有更多的worker,切分的數(shù)量也會相應(yīng)增加。
第一個方案是將來自SQL的邏輯計劃和物理計劃依次生成,然后將物理計劃拷貝到并行worker現(xiàn)場上。這需要對每一個MySQL執(zhí)行計劃里面涉及的數(shù)據(jù)結(jié)構(gòu)全部做克隆操作,且工作量巨大,據(jù)我們了解,當(dāng)前公有云上TOP廠商中,至少有兩家采用了這種方案。不過這種方案存在一些問題,其中廠商投入了大量人力和物力,而另外對MySQL的代碼進(jìn)行了大量的入侵。在后期,你很難跟上社區(qū)的,因為社區(qū)在不斷做代碼重構(gòu)。
第二種方案實際上是一種更常見的商業(yè)數(shù)據(jù)庫方案。當(dāng)SQL語句到達(dá)時,它將生成一個邏輯計劃,并通過拷貝一些環(huán)境數(shù)據(jù)到worker線程,從而生成一個執(zhí)行計劃。這是一個很自然而然的操作。我們目前采用了這種方案,并通過它實現(xiàn)了比其他友商更好的效果,而且只用了他們1/4的人力和時間。這并不是吹牛,如果有機(jī)會大家可以試一試。我們之所以能夠采用這種方案,而其他友商采用了其他的方案,一方面是因為我們從社區(qū)中獲得了一些經(jīng)驗和技術(shù)紅利,另一方面是因為我們參與了社區(qū)的構(gòu)建。社區(qū)在不斷重構(gòu)SQL構(gòu)層,將邏輯計劃和物理計劃分離,通過 iterator機(jī)制拆分得更清晰,這為我們提供了基礎(chǔ),使我們能夠完成這項工作。
第三種方案使用較少。當(dāng)SQL生成邏輯計劃并生成執(zhí)行計劃時,對于需要執(zhí)行不同的物理計劃片段,該方案通過反向編寫成SQL語句的方式來實現(xiàn)。然后,將SQL語句發(fā)送到不同的worker線程上,這些線程可能是ClickHouse。由于ClickHouse無法直接執(zhí)行MySQL執(zhí)行計劃,因此將SQL語句發(fā)送過去,就能夠執(zhí)行了。我們之前也曾經(jīng)嘗試過使用反寫SQL的方式,但是與第一個方案相比,工作量并不見得小,因為基本上必須要把整個執(zhí)行計劃反向一遍。因此,我們采用第二種方案實現(xiàn)了非常好的效果。
我們可以看一下,在TPCH 100G上的性能表現(xiàn)。在DoP為16的情況下,我們基本上有十倍以上的性能提升。我們還有一些能力暫時不支持,因此沒有進(jìn)一步提升。但是,基本上能夠達(dá)到線性提升,因為現(xiàn)在是16DoP,我們有大約十倍的性能提升,這樣的效果非常明顯。
經(jīng)過我們的并行查詢的介紹后,我們想簡要提一下我們投入最大的產(chǎn)品——列存索引,我們期望這個產(chǎn)品未來能夠為用戶帶來更好的效果和使用體驗。在列存索引的友商市場上,我們進(jìn)行了分析比較了Oracle、SQL Server、 TiFlash、MySQL HeatWave等多款產(chǎn)品,綜合各家之長,并結(jié)合我們自身技術(shù),我們成功設(shè)計了列層索引架構(gòu)。
列層索引架構(gòu),相當(dāng)于這是一個RW節(jié)點,這是一個只讀節(jié)點,在只讀節(jié)點上為每張表創(chuàng)建了一個列存的索引,但是我們知道 InnoDB 一個索引最多只支持16個列。相比之下,我們的索引擴(kuò)展性非常強(qiáng),支持最多256列。我們也意識到,在分析型數(shù)據(jù)處理過程中,大寬表是常態(tài),因此在未來可能需要支持更多的列。
當(dāng)數(shù)據(jù)插入時,我們會通過一個redo log以物理復(fù)制的方式將數(shù)據(jù)同步(同步和異步均可)到列存索引中。然后,我們通過Delta Store進(jìn)行并行的回放,實現(xiàn)高效的數(shù)據(jù)插入。
在這個框架中,我們有一個OLAP執(zhí)行器,這個就是MySQL自身的執(zhí)行器,但是我們使用的是統(tǒng)一的優(yōu)化器,可以調(diào)度執(zhí)行計劃,使得哪一部分在列存執(zhí)行,哪一部分在行存執(zhí)行。由于列存索引不斷演進(jìn),其功能可能會不斷擴(kuò)展,因此當(dāng)整個的plan過來的時候,不能完全在我們的列存執(zhí)行,那我們就有一些需要在行存執(zhí)行,所以當(dāng)前我們需要混合的執(zhí)行框架,以實現(xiàn)更好的效果。
在計算過程中,我們也會用到并行計算,剛剛提到的并行計算是MySQL本身,那我們在列存內(nèi)部的話,我們也在構(gòu)建這樣的一個能力。在未來,我期望能夠通過們的優(yōu)化器對查詢語句進(jìn)行整體優(yōu)化,在我們這里執(zhí)行整個分析過程,以提高效率和準(zhǔn)確性。此外,我們還將引入AVX512向量化執(zhí)行,進(jìn)一步提高性能。
這是簡單過一下語句例子,比如說這是一個 Nested Loop Join,假如現(xiàn)在只有這個第一條語句table scan和filter能到列層里面去執(zhí)行,那我們這個執(zhí)行框架是怎么做的呢?首先一條語句來了之后,它會通過這個優(yōu)化器會生成混合的一個執(zhí)行計劃。執(zhí)行計劃就會把這個精細(xì)化,放到這個執(zhí)行調(diào)度里邊去。然后會把其中涉及到列存執(zhí)行的plan,通過這個下壓接口層下壓到Cstore的執(zhí)行器,執(zhí)行器里面我們會并行執(zhí)行,也會進(jìn)行一些原數(shù)據(jù)。例如索引數(shù)據(jù)和粗糙索引,以過濾掉一些大數(shù)據(jù)塊,從而提升效率。此外,我們還有SIMD 的指令的執(zhí)行,最終會把結(jié)果返回到行存,從而會得到最終的結(jié)果。從這里我們可以看出,我們是一個混合的執(zhí)行框架。
在我們的執(zhí)行引擎框架中,我們使用了SIMD指令,即單指令多數(shù)據(jù),這是引擎中一個非常重要的部分。我們有兩張圖,第一張圖顯示了我們采用了SIMD指令和沒有采用SIMD指令但采用了批處理 (即一次處理4096行數(shù)據(jù))的性能比較。我們從TPCH中抽取了一部分?jǐn)?shù)據(jù),大概可以看到我們提升了 5 倍左右的性能,這說明SIMD指令的效果非常明顯。SIMD使用的是英特爾自己的指令集,例如對于一個INT8類型的計算,如果使用普通的指令,一條指令只能執(zhí)行 INT8 加 INT8。但是如果使用英特爾512的AVX512指令,一條指令就可以計算64行數(shù)據(jù),因此效率提升是非常高的。
另外一點,就是我們不采用SIMD的指令,采用了批處理方式一次處理4096行數(shù)據(jù),另一種對比方式就是一行一行的執(zhí)行,我們發(fā)現(xiàn)采用批處理方式可以使性能提升約五倍左右。兩者再結(jié)合的話,性能提升將更為明顯,預(yù)計至少可以提升25倍以上。上面的測試,我們在TPCH 100G的測試場景下進(jìn)行。
接下來,看下通過結(jié)合列存索引和并行查詢的plan情況,這是TPCH Q3一個語句。在這個計劃中上面是一個聚合層(協(xié)調(diào)者),底下是有多個 worker 線程。最底下是列存執(zhí)行的一個計劃,而上面則是行存執(zhí)行的計劃。這個計劃非常好地體現(xiàn)了我們將行列存儲的優(yōu)點相結(jié)合,并加入了并行查詢的能力。這樣做的結(jié)果就是我們具備了整合多方優(yōu)點的能力。
我們在列存中有一個非常重要的一點,那就是Delta Store。為什么我們需要Delta Store呢?當(dāng)你進(jìn)行一個并行回放的時候,數(shù)據(jù)是通過REDO Log同步到列存中的。而Delta Store能夠提供高效的數(shù)據(jù)插入,因為它可以在內(nèi)存中不斷地open only將數(shù)據(jù)往后插入。這樣做的好處是,它能夠提高行級并發(fā),同時我們還有一個insert / delete mask,這使得我們在列存中具備了MVCC的能力。結(jié)合我們在MySQL上的SCN機(jī)制,我們就能夠提供完整的事務(wù)視圖,從而實現(xiàn)完整性的事務(wù)查詢。當(dāng)數(shù)據(jù)插滿后,我們會將其凍結(jié)并把它download到磁盤上去進(jìn)行壓縮,當(dāng)一些數(shù)據(jù)會永久的被被刪掉了,或者說這個數(shù)據(jù)永遠(yuǎn)所有人都能看到了,我們會進(jìn)行一些空洞的compaction。然后再 merge到 main store里面去,其實有點像 LSMtree 的架構(gòu)。
現(xiàn)在我再講一下,我們這個產(chǎn)品中并行查詢部分已經(jīng)上線了,在公有云上已經(jīng)可以使用。而列存索引這部分目前正在內(nèi)部灰度和一些大客戶的試用中,取得了非常好的效果。盡管還沒有正式推出,但我們在PQ查詢的基礎(chǔ)上,我們又有至少三倍以上的性能提升,這是在還沒有完全加入向量化的情況下。而如果在向量化加持之后,我們期望會有更大的性能提升。
目前這個階段的話,我們正在做一些工作,例如并行查詢在MySQL這一部分,我們可能會做MPP。列存的話,我們有可能會開發(fā)自己的MPP,以及包括支持大型的存儲。最后,我想重點談?wù)勎覀兊慕y(tǒng)一內(nèi)核的技術(shù)空間,因為我們知道,公有云和私有云是不同的技術(shù)架構(gòu)。公有云使用共享存儲,而私有云使用分布式存儲。但是我們已經(jīng)將并行查詢擴(kuò)展到了私有云上,這意味著我們公有云和私有云都使用了同一個并行框架。接下來,我們會將列存能力擴(kuò)展到私有云上。這意味著我們一套能力可以在兩個系統(tǒng)上完全復(fù)用。目前來看,我們可能是友商中第一個實現(xiàn)這種統(tǒng)一內(nèi)核的機(jī)制。
今天我的分享就到這兒,謝謝。
本次大會圍繞“技術(shù)進(jìn)化,讓數(shù)據(jù)更智能”為主題,匯聚字節(jié)跳動、阿里云、玖章算術(shù)、華為云、騰訊云、百度的6位數(shù)據(jù)庫領(lǐng)域?qū)<?,深?MySQL x ClickHouse 的實踐經(jīng)驗和技術(shù)趨勢,結(jié)合企業(yè)級的真實場景落地案例,與廣大技術(shù)愛好者一起交流分享。文章來源:http://www.zghlxwxcb.cn/news/detail-437169.html
?文章來源地址http://www.zghlxwxcb.cn/news/detail-437169.html
到了這里,關(guān)于HTAP for MySQL 在騰訊云數(shù)據(jù)庫的演進(jìn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!