Mycat 的分片 join

1.join 概述

Join 絕對(duì)是關(guān)系型數(shù)據(jù)庫(kù)中最常用一個(gè)特性,然而在分布式環(huán)境中,跨分片的 join 確是最復(fù)雜的,最難解決一個(gè)問(wèn)題。

下面我們簡(jiǎn)單介紹下各種 Join 操作。

INNER JOIN

內(nèi)連接,也叫等值連接,inner join 產(chǎn)生同時(shí)符合 A 表和 B 表的一組數(shù)據(jù)。

如圖:

LEFT JOIN

左連接從 A 表(左)產(chǎn)生一套完整的記錄,與匹配的 B 表記錄(右表) .如果沒(méi)有匹配,右側(cè)將包含 null,在 Mysql 中等同于 left outer join。

如圖:

RIGHT JOIN

同 Left join,AB 表互換即可。

CROSS JOIN

交叉連接,得到的結(jié)果是兩個(gè)表的乘積,即笛卡爾積。笛卡爾(Descartes)乘積又叫直積。假設(shè)集合A={a,b},集合 B={0,1,2},則兩個(gè)集合的笛卡爾積為{(a,0),(a,1),(a,2),(b,0),(b,1), (b,2)}??梢詳U(kuò)展到多個(gè)集合的情況。類似的例子有,如果 A 表示某學(xué)校學(xué)生的集合,B 表示該學(xué)校所有課程的集合,則 A 與 B 的笛卡爾積表示所有可能的選課情況。

FULL JOIN

全連接產(chǎn)生的所有記錄(雙方匹配記錄)在表 A 和表 B。如果沒(méi)有匹配,則對(duì)面將包含 null。

性能建議

盡量避免使用 Left join 或 Right join,而用 Inner join

在使用 Left join 或 Right join 時(shí),ON 會(huì)優(yōu)先執(zhí)行,where 條件在最后執(zhí)行,所以在使用過(guò)程中,條件盡可能的在 ON 語(yǔ)句中判斷,減少 where 的執(zhí)行,少用子查詢,而用 join。

Mycat 目前版本支持跨分片的 join,主要實(shí)現(xiàn)的方式有四種。

全局表,ER 分片,catletT(人工智能)和 ShareJoin,ShareJoin 在開(kāi)發(fā)版中支持,前面三種方式 1.3.0.1 支持

2.全局表

一個(gè)真實(shí)的業(yè)務(wù)系統(tǒng)中,往往存在大量的類似字典表的表格,它們與業(yè)務(wù)表之間可能有關(guān)系,這種關(guān)系,可以理解為“標(biāo)簽”,而不應(yīng)理解為通常的“主從關(guān)系”,這些表基本上很少變動(dòng),可以根據(jù)主鍵 ID 進(jìn)行緩存,下面這張圖說(shuō)明了一個(gè)典型的“標(biāo)簽關(guān)系”圖:

在分片的情況下,當(dāng)業(yè)務(wù)表因?yàn)橐?guī)模而進(jìn)行分片以后,業(yè)務(wù)表與這些附屬的字典表之間的關(guān)聯(lián),就成了比較棘手的問(wèn)題,考慮到字典表具有以下幾個(gè)特性:

? 變動(dòng)不頻繁

? 數(shù)據(jù)量總體變化不大

? 數(shù)據(jù)規(guī)模不大,很少有超過(guò)數(shù)十萬(wàn)條記錄。

鑒于此,MyCAT 定義了一種特殊的表,稱之為“全局表”,全局表具有以下特性:

? 全局表的插入、更新操作會(huì)實(shí)時(shí)在所有節(jié)點(diǎn)上執(zhí)行,保持各個(gè)分片的數(shù)據(jù)一致性

? 全局表的查詢操作,只從一個(gè)節(jié)點(diǎn)獲取

? 全局表可以跟任何一個(gè)表進(jìn)行 JOIN 操作

將字典表或者符合字典表特性的一些表定義為全局表,則從另外一個(gè)方面,很好的解決了數(shù)據(jù) JOIN 的難題。

通過(guò)全局表+基于 E-R 關(guān)系的分片策略,MyCAT 可以滿足 80%以上的企業(yè)應(yīng)用開(kāi)發(fā)。

配置

全局表配置比較簡(jiǎn)單,不用寫(xiě) Rule 規(guī)則,如下配置即可:

<table name="company" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" />

需要注意的是,全局表每個(gè)分片節(jié)點(diǎn)上都要有運(yùn)行創(chuàng)建表的 DDL 語(yǔ)句

3.ER Join

MyCAT 借鑒了 NewSQL 領(lǐng)域的新秀 Foundation DB 的設(shè)計(jì)思路,F(xiàn)oundation DB 創(chuàng)新性的提出了 TableGroup 的概念,其將子表的存儲(chǔ)位置依賴于主表,并且物理上緊鄰存放,因此徹底解決了 JION 的效率和性能問(wèn)題,根據(jù)這一思路,提出了基于 E-R 關(guān)系的數(shù)據(jù)分片策略,子表的記錄與所關(guān)聯(lián)的父表記錄存放在同一個(gè)數(shù)據(jù)分片上。

customer 采用 sharding-by-intfile 這個(gè)分片策略,分片在 dn1,dn2 上,orders 依賴父表進(jìn)行分片,兩個(gè)表的關(guān)聯(lián)關(guān)系為 orders.customer_id=customer.id。于是數(shù)據(jù)分片和存儲(chǔ)的示意圖如下:

這樣一來(lái),分片 Dn1 上的的 customer 與 Dn1 上的 orders 就可以進(jìn)行局部的 JOIN 聯(lián)合,Dn2 上也如此,再合并兩個(gè)節(jié)點(diǎn)的數(shù)據(jù)即可完成整體的 JOIN,試想一下,每個(gè)分片上 orders 表有 100 萬(wàn)條,則 10 個(gè)分片就有 1 個(gè)億,基于 E-R 映射的數(shù)據(jù)分片模式,基本上解決了 80%以上的企業(yè)應(yīng)用所面臨的問(wèn)題。

配置

以上述例子為例,schema.xml 中定義如下的分片配置:

<table name="customer" dataNode="dn1,dn2" rule="sharding-by-intfile">

<childTable name="orders" joinKey="customer_id" parentKey="id"/>

</table>

4.Share join

ShareJoin 是一個(gè)簡(jiǎn)單的跨分片 Join,基于 HBT 的方式實(shí)現(xiàn)。

目前支持 2 個(gè)表的 join,原理就是解析 SQL 語(yǔ)句,拆分成單表的 SQL 語(yǔ)句執(zhí)行,然后把各個(gè)節(jié)點(diǎn)的數(shù)據(jù)匯集。

配置

支持任意配置的 A,B 表如:

A,B 的 dataNode 相同:

<table name="A" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />

<table name="B" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />

A,B 的 dataNode 不同

<table name="A" dataNode="dn1,dn2 " rule="auto-sharding-long" />

<table name="B" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />


<table name="A" dataNode="dn1 " rule="auto-sharding-long" />

<table name="B" dataNode=" dn2,dn3" rule="auto-sharding-long" />

代碼測(cè)試

先把表 company 從全局表修改下配置

<table name="company" primaryKey="ID" dataNode="dn1,dn2,dn3" rule="mod-long" />

重新插入數(shù)據(jù)

下面可以看下普通的 join 和 sharejoin 的區(qū)別:

5.catlet(人工智能)

解決跨分片的 SQL JOIN 的問(wèn)題,遠(yuǎn)比想象的復(fù)雜,而且往往無(wú)法實(shí)現(xiàn)高效的處理,既然如此,就依靠人工的智力,去編程解決業(yè)務(wù)系統(tǒng)中特定幾個(gè)必須跨分片的 SQL 的 JOIN 邏輯,MyCAT 提供特定的 API 供程序員調(diào)用,這就是 MyCAT 創(chuàng)新性的思路——人工智能。

以一個(gè)跨節(jié)點(diǎn)的 SQL 為例

Select a.id,a.name,b.title from a,b where a.id=b.id

其中 a 在分片 1,2,3 上,b 在 4,5,6 上,需要把數(shù)據(jù)全部拉到本地(MyCAT 服務(wù)器),執(zhí)行 JOIN 邏輯,具體過(guò)程如下(只是一種可能的執(zhí)行邏輯):

EngineCtx ctx=new EngineCtx();//包含 MyCat.SQLEngine

String sql=,“ select a.id ,a.name from a ” ;

//在 a 表所在的所有分片上順序執(zhí)行下面的本地 SQL

ctx.executeNativeSQLSequnceJob(allAnodes,new DirectDBJoinHandler());

DirectDBJoinHandler 類是一個(gè)回調(diào)類,負(fù)責(zé)處理 SQL 執(zhí)行過(guò)程中返回的數(shù)據(jù)包,這里的這個(gè)類,主要目的是用 a 表返回的 ID 信息,去 b 表上查詢對(duì)于的記錄,做實(shí)時(shí)的關(guān)聯(lián):

DirectDBJoinHandler{

Private HashMap rows;//Key 為 id,value 為一行記錄的 Column 原始 Byte 數(shù)組,這里是a.id,a.name,b.title 這三個(gè)要輸出的字段

Public Boolean onHeader(byte[] header){

//保存 Header 信息,用于從 Row 中獲取 Field 字段值

}

Public Boolean onRowData(byte[] rowData){

String id=getColumnAsString(“ id” );

//放入結(jié)果集,b.title 字段未知,所以先空著

rows.put(getColumnRawBytes(“ id” ),rowData);

//滿 1000 條,發(fā)送一個(gè)查詢請(qǐng)求

String sql=” select b.id, b.name from b where id in (………….)” ;

//此 SQL 在 B 的所有節(jié)點(diǎn)上并發(fā)執(zhí)行,返回的結(jié)果直接輸出到客戶端

ctx.executeNativeSQLParallJob(allBNodes,sql ,new MyRowOutPutDataHandler(rows));

}

Public Boolean onRowFinished(){}

Public void onJobFinished(){

If(ctx.allJobFinished()){

{///used total time ….}

}

}

最后,增加一個(gè) Job 事件監(jiān)聽(tīng)器,這里是所有 Job 完成后,往客戶端發(fā)送 RowEnd 包,結(jié)束整個(gè)流程。

ctx.setJobEventListener(new JobEventHandler(){public void onJobFinished(){ client.writeRowEndPackage()}});

以上提供一個(gè) SQL 執(zhí)行框架,完全是異步的模式執(zhí)行,并且以后會(huì)提供更多高質(zhì)量的 API,簡(jiǎn)化分布式數(shù)據(jù)處理,比如內(nèi)存結(jié)合文件的數(shù)據(jù) JOIN 算法,分組算法,排序算法等等,期待更多的牛人一起來(lái)完善

6.Spark/Storm 對(duì) join 擴(kuò)展

看到這個(gè)標(biāo)題,可能會(huì)感到很奇怪,Spark 和 Storm 和 Join 有關(guān)系嗎? 有必要用 Spark,storm 嗎?

mycat 后續(xù)的功能會(huì)引入 spark 和 storm 來(lái)做跨分片的 join,大致流程是這樣的在 mycat 調(diào)用 spark,storm的 api,把數(shù)據(jù)傳送到 spark,storm,在 spark,storm 進(jìn)行 join,在把數(shù)據(jù)傳回 mycat,mycat 在返回給客戶端。


本文摘抄于:mycat用戶指南

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容