騰訊云數據庫國產數據庫專題線上技術沙龍正在火熱進行中,3月19日唐顥的分享已經結束,沒來得及參與的小伙伴不用擔心,以下就是直播的視頻和文字回顧。
關注“騰訊云數據庫”公眾號,回復“0319唐顥”,即可下載直播分享PPT。
今天分享的主題是TDSQL-SQL引擎架構的演進和查詢優化實戰。今天分享分為四章,分別是:TDSQL簡介、SQL引擎簡介、SQL引擎查詢處理和最佳實踐。
點擊觀看直播回放
PartⅠ TDSQL分庫分表策略

前面的課程中,我們已經對TDSQL的架構做了比較詳細的介紹,這里我們簡單回顧一下TDSQL。TDSQL是騰訊針對金融行業推出的一款自主可控、高一致、分布式、HTAP數據庫產品,目前已為超過500+金融政企提供數據庫服務,行業涵蓋了銀行、保險、證券信托、互聯網金融等等行業。

TDSQL是Shared-Nothing架構的分布式數據庫,這張圖是TDSQL的核心架構圖,在這個架構圖中包含了三個重要組件,分別是SQL引擎、MetaCluster和后端SET。其中每個SET是由一主多備構成的高可用復制單元,在一個TDSQL中往往包含多個這樣的SET。每一個SET負責存儲分布式表的部分分片信息。SQL引擎負責處理業務發過來的SQL請求,然后對SQL進行拆分,發送給各個SET進行處理,并對每個SET返回的結果進行聚合,得到最終的結果。
在TDSQL中,每個SET都會負責一段連續的哈希;在TDSQL中建立的每一個分布式表,SQL引擎都要求用戶指定其中的一個列為分區鍵,SQL引擎通過計算這個分區鍵的哈希值,將這個表的每一行數據都映射到這個哈希空間,由對應的SET進行存儲。哈希空間與SET之間的對應關系,我們叫做路由表。這個路由信息會存儲在MetaCluster里。當對整個集群進行縮容或擴容時,每個SET對應的哈希空間也會發生變化,對應的數據也會進行搬遷。SQL引擎通過監聽MC來感知集群的變化。

在建表的時候,SQL引擎通過關鍵字讓用戶在建表的時候指定其中的一個列為分區鍵。在這個例子中,用戶建立一張表,其中指定ID為shardkey,也就是說SQL引擎通過計算分區鍵ID的哈希值,將這個表的數據進行打散,均勻的分布在各個SET上。
PartⅡ TDSQL-SQL引擎如何優雅處理海量SQL邏輯
前面我們回顧了一下TDSQL的整體架構,以及Sharding策略。這里我們再介紹一下SQL引擎。

目前TDSQL-SQL引擎已經能夠支持絕大多數的MySQL語法,分布式查詢、事務和死鎖檢測。應用程序端可以像使用單機數據庫一樣,通過SQL引擎來使用整個TDSQL。除了這些比較基本的功能,SQL引擎還支持一些比較高級的功能,例如SQL防火墻、讀寫分離等等。
我們這里通過一條SQL的大體執行路徑來看一下這些功能之間的關系:
應用程序通過MySQL客戶端向SQL引擎發送了一條SQL,SQL引擎通過協議解析,從數據包中得到這條SQL,并對這條SQL進行語法解析,語法解析以后我們就得到一棵抽象的語法樹,如果應用配置了SQL防火墻,我們還會匹配防火墻的規則,判斷這條SQL能否執行。如果能夠執行的話,接著我們會構建這條SQL的分布式執行計劃——在這個計劃里面,我們描述了由哪些SET參與查詢的執行,每個SET應該執行什么樣的邏輯,SQL引擎又進行怎樣的聚合,兩者之間怎么進行協調。得到分布式執行計劃以后,我們將這個計劃再轉換成SQL的形式發送給對應的SET執行。接著我們執行讀寫分離算法,從每個SET中挑選出最適合訪問的實例,然后就可以向這個實例發送SQL了。我們收到每個SET反饋的響應以后,對返回的結果進行聚合。這里的聚合邏輯主要是執行分布式執行計劃分配給SQL引擎的一些任務。如果是一條簡單的查詢,我們通過流式聚合就可以得出最終的結果。并將結果反饋給應用;如果是一條比較復雜的查詢,往往需要拆分成多個階段來執行。這個時候就需要構建下一個階段的分布式執行計劃,然后再執行這個計劃。經過多次執行,所有的階段全部執行完畢之后,最終在本地的執行器中進行最終的計算和聚合,從而得到一個最終的結果。
PartⅢ 如何實現高性能SQL引擎查詢
我們這里已經介紹了SQL引擎的一個大體的功能,這里我們再具體介紹SQL引擎是怎么處理各類查詢的。我們將查詢分成兩類,一類是Select查詢,一類是更新操作,例如Delete、Update、Insert等等。對Select查詢的話,我們有兩種處理方式:一種是流式處理模型,一種是通用處理模型。流式處理模型主要是處理單表上的查詢,而通用處理模型是對流式處理模型的彌補,負責處理分布式的跨節點查詢。

3.1 流式處理模型原理及典型案例詳解
我們先介紹一下流式處理模型。這里有一個簡單的例子

在這個例子里面用戶訪問的是一個日志表,這個日志表里面有三個列:其中ID是日志的ID,name是用戶名,score是用戶的歷史游戲得分。一個用戶會有多個游戲得分,并且他的游戲得分的記錄會分散在各個SET上。業務想要獲取每個用戶的平均分,SQL引擎不能直接把SQL發送給各個SET,所以他需要計算出每個用戶的總得分和這個用戶在這張表上的一個總記錄數,然后用兩者的商來求得每個用戶的平均分——具體來說SQL引擎要求每個SET返回,每個用戶在每個SET上的一個局部的總得分和總記錄數。接著SQL引擎將每個SET上返回的結果再進行聚合,得到每個用戶的總得分和總記錄數,然后再用兩者相除。

我們發現,SET執行的SQL里面有一個order by,這個是做什么的呢。我們假設沒有這個order by,那么某一個用戶張三,SET1反饋的第一條記錄是張三的局部得分,SQL引擎拿到這個張三的結果以后,無法直接計算出張三這個用戶的平均分,他還需要知道張三在SET2上的得分。但是SET2可能在最后一條記錄才返回張三在SET2的局部的得分,所以SQL引擎不得不進行等待操作,等待SET2返回所有的結果,而這個等待操作會非常影響性能。如果我們增加了這個order by,SET1和SET2返回的結果都是按名字有序地進行,SQL引擎進行一個簡單的Merge就可以得到一個全局有序的結果。對張三這個用戶來說,這個有序的結果里面,他在SET1和SET2上的局部得分就是相鄰的,所以SQL引擎不需要等待SET1和SET2反饋的所有結果,他直接就能計算出張三的平均分。這個引擎計算出張三的平均分以后,立馬就可以將張三的得分再反饋給業務。
在這個例子中可以看到,SET1和SET2不停地向SQL引擎返回數據,SQL引擎隨即對返回的結果進行聚合,并將聚合結果立即返回給這里。整個過程就像流水一樣,所以我們將這個過程稱之為流式處理模型。流式處理模型最核心的地方就是對SQL進行拆分——拆分成兩部分,一個是SET執行的部分,以及在SQL引擎執行的部分。就拿剛剛的例子來說,SET進行一個局部的聚合,計算出每個用戶在SET上的局部的總得分和總記錄數。SQL引擎進行一個全區的累加和聚合,得到每個用戶的總得分和總記錄數。進行拆分以后,流式處理模型還會添加一些額外的操作,將兩者銜接起來——例如剛剛例子中的order by,這樣一來我們就得到了一個流式處理的執行計劃。當然除了這個以外,我們還會進行一些優化,將原本分配給SQL引擎的一些操作進行下推,例如模型中的Limit和distinct,其實它應該在SQL引擎上執行的。我們通過把這些下推,能夠較大地減少SET返回給SQL引擎的數據量,從而也就提升了整個執行的性能。
剛才我們一直強調流式處理模型是針對單表處理的,事實上它還能夠處理其他的場景。

例如這個例子1中的表,兩張表的shardkey相等,因此我們可以把t1、t2當成一個整體,當成一個整體之后我們就可以用剛剛介紹的查詢拆分構建執行計劃,并用流式處理模型進行處理了。對子查詢的話,類似這里的IN,a是T1和B1的shardkey,這個子查詢同樣暗含著T1的shardkey等于B的shardkey,我們同樣將T1和這個子查詢當成一個整體,套用剛剛介紹的查詢拆分和流式處理模型進行處理。
當然,并不是所有的查詢都能夠滿足這樣的一個情況,如果兩個表不是shardkey相等的話,這個時候我們就需要用后面的通用處理模型進行處理了。但是通用處理模型的性能比不上流式處理模型,那怎樣才能夠將流式處理模型進行進一步推廣呢?TDSQL就引入了一個廣播表——廣播表的意思就是說將一些表的數據全量備份在每個節點上,這樣一來原本T1、T2的關聯查詢,他們必須用通用處理模型進行處理,這個時候我們也可以使用流式處理模型進行處理了。

從剛剛的介紹,我們可以看到流式處理模型是以pipeline的方式執行,SET不斷返回數據給SQL引擎,SQL引擎不停地對返回的結果進行聚合,并將聚合的結果立即返回給應用。所以說在這種處理方式下,SQL引擎的內存開銷是非常低的。同時在執行的過程中,各個SET是并發執行,這也保證了流式處理模型的性能、并行性。流式處理模型最核心的一方就是拆分和下推——通過智能的拆分和下推,我們將大量的計算下推給SET執行,這樣就大大減少了SQL引擎需要從SET獲取的數據。流式處理模型雖然要求比較嚴苛,但是我們通過合理的選擇shardkey以及引入廣播表,事實證明流式處理模型其實能夠滿足絕大多數的OLTP業務。
3.2 通用處理模型:跨節點分布式查詢優化的利器
接下來我們介紹一下SQL引擎的通用處理模型。

通用處理模型主要是針對分布式的跨節點查詢。說到分布式的跨節點查詢,大家首先想到的肯定是Spark、Greenplum這樣的大數據處理引擎。在這些引擎中,他們執行查詢的時候往往需要在節點之間進行大規模的數據搬遷,因為TDSQL主要針對OLTP業務,所以在生產上,TDSQL往往運行著大量的交易SQL,進行大規模數據搬遷肯定是不現實的。所以,TDSQL基于常見的OLTP場景而設計了自己的分布式處理查詢框架。在這個模型下,SQL引擎對SQL進行語法解析以后,就將實際參與查詢的數據加載到SQL引擎,然后在本地執行這個查詢。在我們所設想的OLTP場景下,用戶常常為一個表的索引指定一個常量或者常量的范圍,表之間的連接也基本上為等值連接。在這樣的一個場景下,SQL引擎通過查詢下推和條件下推大大降低了需要加載的數據量,從而使得這個方案變得切實可行。
這里我們以一個例子來講解通用數據模型是怎樣處理一條SQL的。

在這個例子中一共有三張表,每個表中的shardkey我們都設置為A。SQL先將T1、T2進行一個等值連接,然后where條件指定了T1.A是一個常量;在這里還有一個子查詢——這個子查詢是一個相關子查詢,它引用了外層的T1.C。在執行這條查詢的時候,SQL引擎首先選擇一個需要加載的表,在這里我們選擇了T1.A,因為它包含了一個可以下推條件,而且條件是一個主鍵。我們加載完T1以后,就可以知道T1.B和T1.C是兩個列的范圍了,根據這個連接的連接條件,我們可以推算出T2.A的范圍。根據推算出來的T2.A的范圍我們繼續加載T2。這樣一來,就可以將上層涉及的兩個表T1、T2都加載到本地。接著我們處理內層的子查詢,這個子查詢是一個相關子查詢,如果我們在加載T2的時候發現T1.C其實是一個常量,這個時候就可以將這個相關子查詢轉換成一個非相關子查詢,并將這個子查詢提取出來進行獨立計算。計算以后我們將它的結果來替換這個子查詢;如果它不是一個常量的話,我們就利用這個條件推斷出T3.A的范圍,再用推算出來的這個條件去加載T3,這樣一來,這條SQL所設計的所有的表的數據,我們都加載到了SQL引擎,接下來就像MySQL一樣執行這條查詢就可以了。
通過這個例子我們可以看到,SQL引擎通過條件下推,并利用加載的數據推算出新的條件,然后利用新的條件再去過濾我們需要加載的表,這樣可以大大降低需要加載的數據量。對于子查詢的話,如果我們發現它能夠轉換成非相關詞查詢,這個時候我們還會進行子查詢的下推。當然具體優化的技術還有很多,這里我們就不再一一列舉。
我們將優化和工程實踐中所使用的一些技術進行一個分類,主要包括邏輯優化、條件下推和隔離。

邏輯優化:主要是對SQL的結構進行優化,使它變得更加容易處理。例如我們將左/右連接轉換成內連接。如果它能夠轉換——在原來的邏輯下需要先加載左連接的左表,然后才能加載左連接的右表。最后轉換以后,我們就可以消除這種限制,能夠生成多種加載方式,這樣的話我們就可以有更好的一個優化的空間。
條件下推:是指用一些手段將SQL中的條件提取出來,或者說我們利用已知的一些信息推斷出新的條件,用這些推斷出來的條件來過濾需要加載的數據。同時我們還可以通調整加載的順序,例如剛剛例子中我們優先加載了T1,利用優先加載小表的策略同樣能夠起到降低需要加載的數據量的作用。
隔離:TDSQL主要針對OLTP業務,所以它線上會運行著大量的交易SQL,這個時候如果應用發送過來的是一個復雜的查詢、是一個OLAP類的查詢的話,往往需要加載很大的數據量。而且執行的時候也會有很大的CPU開銷,為了不影響這些正在運行的OLTP業務,我們需要進行隔離。比如說我們將比較耗時的操作,例如把數據加載過來,然后緩存在本地的臨時表里,以及最終要執行查詢的時候,也將這個比較耗時的操作放在后臺異步執行,這樣就可以對OLTP業務進行隔離,避免影響在線的一個交易。
3.2.1 通用處理模型總結

通過前面我們可以看到通用處理模型的SQL兼容性是非常好的,因為我們只需要將數據加載到本地,然后用傳統的方法執行這個查詢就可以了。然后我們對OLTP場景有很多的優化策略,通過這些策略,我們大大降低了需要加載的數據量。同時,這個通用處理模型也可以作為OLAP來用,如果當做OLAP來用的話,我們會將數據加載和執行這兩個比較耗時的動作在后臺異步執行。
3.3 TDSQL-SQL引擎更新操作原理
前面我們講解了SQL引擎如何處理Select的查詢。這里我們再簡單介紹一下SQL引擎是如何處理更新操作的。
3.3.1 簡單更新操作

對于一些簡單的更新操作,例如這里的Insert、Update語句,我們根據SQL中的shardkey對這些SQL進行拆分。例如INSERT,它插入這些數據,我們根據它的shardkey計算出2、3是需要插入到SET1的;1和4是需要插入到SET2的。我們將這些需要插入的數據進行拆分以后,再構建對應的Insert語句分別發送給SET1和SET2進行執行。如果一條更新語句沒有帶shardkey,例如這里的Delete語句,這個時候我們就需要將這條更新操作廣播給所有的SET執行。如果一條更新語句更新了多個SET,我們就會使用分布式事務來保證這個更新操作的原子性。
3.3.2 復雜更新操作

而對于一個比較復雜的更新操作,例如這個例子里面的聯合更新SQL。對于這樣一個復雜的SQL,SQL引擎會將它拆分成兩個部分:一部分是Select,一部分是對應的更新部分。對于這個語句來說就是一條Update。而Select的話,它主要的目的是提取出那些需要被更新行的主鍵,以及我們需要設置的新值。獲取這兩個關鍵信息以后,我們會構建對應的更新操作,因為這個例子里面就是一條Update語句——在這個語句里面我們指定了需要被更新行的主鍵,同時我們也指定了需要被更新的列和它的新值;然后將這條Update語句發送給對應的SET執行。對于這條Select語句的話,我們就看它的類型,看它是否shardkey相等——如果shardkey相等的話,我們就將由流式處理模型先處理;如果不相等,我們就用通用處理模型先處理。
3.3.3 更新操作中的分布式事務

前面我們多次提到分布式事務,在前面的課程中,我的同事也對分布式事務做了一些講解。這里我們再簡要回顧一下。SQL引擎分布式事務所使用的算法是兩階段提交,對應用來說其實不需要關心具體的實現細節,對應用來說就是簡單的Commit——當業務發送Commit到SQL引擎的時候,SQL引擎就會向所有的參與者發送prepare,接下來每個收到prepare的主機將這個事務的狀態設置成prepare狀態,并將這個事務所產生的binlog全部發送給備機。備機收到以后就會再向主返回一個應答,主再向SQL引擎返回一個應答,SQL引擎收到所有參與者的應答之后就會做一個決策。當所有的參與者都應答成功,它就會做一個提交的決策,并將這個決策寫入到分布式的事務日志中。一旦寫成功的話,我們就可以直接將這個事務提交;而當發生任何一種故障,我們都可以根據這個全局的分布式事務日志進行提交或者回滾。
3.3.4 更新操作自增列優化原理

使用數據庫的過程中,我們經常會使用自增列。SQL引擎也提供了這個功能,當應用創建表的時候,如果指定了一個自增列,SQL引擎就向一個全局的元數據表中插入一個記錄,這個記錄包含了shardkey的名稱,以及下一個可以使用的值。當應用后續再發送INSERT語句過來的時候,SQL引擎就會對記錄中這個值進行加1,然后再用原來的值來填充這條INSERT語句,再將這條填充后的Insert語句進行拆分并發送到對應的SET執行。如果對每一條Insert語句我們都去訪問這一條記錄,這一條記錄必然會成為一個熱點,繼而對整個系統的穩定性和性能都會產生很大的影響。所以SQL引擎丟棄了自增的屬性,只保留了它全區唯一的屬性。SQL引擎為了做到這一點,在每次獲取自增列值的時候會一次性獲取多個,然后再緩存到本地。當應用發送Insert 語句過來,就直接從本地的cache中拿出一個值來填充這個Insert ,避免熱點的產生,從而也提升了Insert語句的性能。當然,如果用戶非得要使用遞增值,SQL引擎還提供序列功能,通過序列來滿足單調遞增的屬性。
PartⅣ TDSQL-SQL引擎查詢最佳實踐
前面我們介紹了SQL引擎是如何處理各類查詢的,接下來是我們的最佳實踐。在這一章節我們會介紹選擇廣播表的基本原則;SQL引擎提供的基本命令等,通過這些命令我們可以看到一條SQL具體的執行細節。
4.1 廣播表
使用廣播表可以讓一條SQL使用流式處理的方式進行處理,流式處理的性能往往是比較高的。那么什么樣的一個表適合作為廣播表呢?

對于廣播表,SQL引擎需要將這個表全量備份到所有的SET上,這會產生空間上的消耗;同時對廣播表的每一次更新,都需要使用分布式事務,從而保證這個更新操作的一致性。因此,我們優先要選取的表,會希望它的數據量比較小,來減少對空間的占用;同時我們希望它的更新頻率比較低,這樣能夠降低對更新操作性能的影響。我們使用廣播表主要是為了優化連接查詢,所以說我們選擇的廣播表本身,它應該經常被訪問,當滿足這兩個條件,我們就可以建議用戶將這樣的一個表設置成廣播表。
4.2 explain信息解讀

在使用MySQL的時候,我們經常使用的命令就是explain,通過explain我們可以看到查詢的執行計劃,看到這條SQL是否使用了某個索引,或者說多表連接的順序是否符合預期,SQL引擎也提供了這樣一個功能。剛才我們說過一條select語句的執行方式有兩種:一種是流式處理模型,一種是通用處理模型。對流式處理模型來說,SQL引擎會拆分成兩部分,一個是SET執行部分和SQL引擎執行部分。如果SQL引擎執行的邏輯比較簡單,這個時候explain所產生的結果就是SET上的一個實際執行計劃,例如對這條SQL來說,其實SQL引擎并沒有做什么比較大的計算,所以它產生的結果其實是MySQL上的執行計劃。SQL引擎還會追加一些額外的信息,例如可以看到提示用戶這條SQL是發給哪個SET的,實際發給SET的是怎樣的一條SQL。

如果SQL引擎對SQL在進行流式處理的過程中進行了比較復雜的聚合,例如——對這條SQL來說,SQL引擎需要計算出count(distinct b),這個時候explain產生的結果就跟前面不一樣,explain會告訴用戶DB上執行的是什么樣的查詢,SQL引擎進行怎樣的聚合。這個例子里面,我們可以看到DB上執行的是掃描查詢,并且下推了distinct,在DB部分進行了初步去重。如果想要知道下推部分的執行計劃,我們還提供了透傳命令——通過透傳命令我們可以看到這條SQL在每個SET上的具體執行計劃。這個例子里面,我們可以看到,為了執行這個計劃,每個SET使用的臨時表,并且進行了一個排序。

對于使用通用處理模型處理的查詢,explain展示的信息又會不一樣。前面我們說過在通用處理模型下,我們需要對表進行加載,因此explain輸出的結果就是告訴我們,SQL引擎到底使用了什么條件去加載數據。對于推導出來條件,explain會添加一個前綴/*esteimated*/加以提示。如果子查詢可以直接下推,explain同樣也會展示出來。在展示怎么樣加載數據和怎么樣下推查詢之后,explain會展示最終SQL引擎要執行的查詢。
4.3 trace:展示SQL各個階段的耗時

當然光知道一條SQL是怎么執行,有時候還是不夠的的。因為影響一條SQL的執行效率可能還跟當前的環境、負載有關系。所以我們想知道一條SQL在實際執行過程中各個階段的時耗,SQL引擎就提供了這樣一個強大的功能——trace。當你在SQL的前面加一個trace前綴的時候,SQL引擎會執行這條查詢并記錄在執行過程中各個階段的時耗。例如在這個例子里面,這條SQL是以使用通用處理模型進行處理的,所以在展示的結果里面,我們可以清晰地看到,加載T1時,從SET1和SET2加載數據的時耗,以及SET1和SET2返回的數據量。通過這些信息,我們就可以看到在數據加載過程中的具體細節。如果時耗比較大的話,我們就再去翻看前面的EXPLAIN信息,看看它的下推是否正常,下推之后是否能夠使用到索引。通過這些信息我們就可以清楚的看到一條SQL在各個階段所占用的時間,結合前面介紹的的explain命令,就可以很方便地定位到性能上的瓶頸了。
4.4 show processlist

另外我們在MySQL中經常使用的一個命令還有show processlist,這個命令可以看到當前性能中正在運行的一些查詢,SQL引擎也同樣提供了這個命令。通過這條命令可以看到系統中當前正在運行的查詢,通過觀察查詢執行時從后端DB加載的數據量,以及時耗,我們可以方便地定位到這個系統中哪條查詢是資源的消耗大戶。show processlist輸出中還有一個關鍵的字段,extra,因為SQL引擎會對用戶發送過來的SQL進行拆解,實際發送給DB的SQL跟原生的SQL已經不太一樣,extra會展示這些被拆分以后得到的SQL及其實際執行的時間。這樣我們就可以將DB上的SQL和當前正在運行的業務SQL結合起來,如果我們發現DB上被某條SQL占用了大部分資源,我們就可以通過這些信息將其與一條業務的SQL進行一個關聯。

當然,如果是DB出現慢查詢的時候,你剛好在電腦旁邊的話,就可以用剛剛說的show pracesslist進行查看。如果你不在電腦旁邊,當回到電腦旁邊的時候,這個高峰期已經過去了,那怎么辦?SQL引擎會將應用發過來的SQL,以及拆分過的SQL記錄到日志中。通過日志分析工具,例如這個例子,可以看到當時SQL引擎對這條SQL的拆分,以及每條被拆分的SQL在哪個時間點發送到了哪一個SET,同時還展示每條SQL的影響行數及返回的數據量。通過日志分析工具,我們可以還原出現問題的時候當時的現場,從而進一步對業務的SQL進行分析和優化。
PartⅤ Q&A
Q:SQL引擎是自己開發的還是用的MySQL的引擎?
A:SQL引擎是我們自己開發的。
Q:如果做數據庫從Oracle換成TDSQL,對應用來說需要的變更很大嗎?
A:TDSQL與Oracle在語法上會有一些差異,我們的一些客戶也是從Oracle遷移到TDSQL來的,實踐證明,只需要一點點改造,將部分Oracle 的SQL替換成與之相對應的TDSQL語法即可。
Q:如果業務單表數量小的情況是不是不推薦使用這種分庫分表的方式?請問隨著業務的發展,當數量擴展到多少時,數據庫推薦分庫分表?
A:數據量比較小的時候自然不需要使用分庫分表。當數據量在可預期的時間范圍內,它可能會超過單機能夠承受的范圍,比如說當可能有上T的數據時,就需要考慮分庫分表了。另外,當一臺機器的計算能力滿足不了業務的話,也可以使用分庫分表,SQL引擎通過將計算進行下推,使得計算能力隨著節點數而線性增長。所以說我們當出現容量或者計算能力上單機無法滿足的情況時,我們就可以使用分庫分表。
Q:這個SQL引擎類似于Oracle 優化器或sharding?開發者不用過度關注吧?
A:你用SQL引擎的話,使用TDSQL可以像使用單機MySQL一樣使用SQL引擎,一般來說你是不需要過度關注的。
Q:參數在每個SET上執行的時候也是走事務嗎?不然每個SET的原子性沒法保證吧?
A:是的,通過SQL引擎開啟一個事務的時候,SQL引擎也會在每個SET上開啟相應的子事務。
Q:分布式事務是基于MySQL原生的兩階段提交,不是基于BASE,兩階段提交性能會不會很差?
A:分布式事務的話,我們是基于原生的MySQL所提供的XA功能,但是在真正上線之前,其實我們對它做了很大的一個改造,就是說其實跟開源差別比較大。在實際使用過程中,兩階段提交會有一些性能影響,但是性能影響不是特別大,基本上影響可能在20%左右。
Q:Squence的實現只是保證遞增,不保證連續性嗎?如果可以實現單調遞增,具體的實現邏輯是怎么樣的?
A:Squence的話,是可以保證連遞增的,每次獲取新值都需要訪問元數據表。
Q:開發者應該需要關注TDSQL的語法嗎?比如說建表的時候需要指定shardkey之類的。
A:前面的課程已經講解過。如果建表的時候沒有指定shardkey——TDSQL會自己選擇一個shardkey,但是該功能默認是關閉的。為什么呢?如果你沒有參與到選擇shardkey的過程,TDSQL沒法保證這個shardkey的選擇是最合適的,因為TDSQL不知道業務邏輯是怎么訪問這張表的。
如果后續還有什么其他問題的話,歡迎在我們的技術交流群溝通。好的,今天我們的分享就到這里,再見!
特惠體驗云數據庫

