MyCat Join 專題 ---- share join

share join:分片表 join

目錄

零:分片表實操


 

零:分片表實操

ShareJoin 是一個簡單的跨分片 Join,目前支持 2 個表的 join,原理就是解析 SQL 語句,拆分成單表的 SQL 語句執行,然後把各個節點的數據彙集。有限制,不同分盤規則最多兩表操作

受限制的原因主要在於:各表的分片後的數據可能不在同一個分片中。所以會導致問題。

特殊情況:多個表使用同一種分片規則,且分片規則屬性相同。在 share join 可以支持多與兩表的查詢。以下是測試樣例:

schemel.xml,注意點就是我添加了兩個範圍分片的表 wyptable lxjtable

<mycat:schema xmlns:mycat="http://io.mycat/">
    <schema name="mydb" checkSQLschema="true" sqlMaxLimit="100">
        <table name="lsqtable" primaryKey="id" autoIncrement="true" dataNode="dn$1-2" rule="mod-long" >
            <childTable name="lsqtable_supplement" primaryKey="id" joinKey="id" parentKey="id" >
                <childTable name="lsqtable_supplement_items" joinKey="parent_id" parentKey="id" />
            </childTable>
            <childTable name="lsqtable_supplement_other" primaryKey="id" joinKey="id" parentKey="id" />
        </table>
        <table name="wyptable" primaryKey="id" autoIncrement="true" dataNode="dn$1-2" rule="auto-sharding-long" />
        <table name="lxjtable" primaryKey="id" autoIncrement="true" dataNode="dn$1-2" rule="auto-sharding-long" />
        <table name="jointable" primaryKey="id" type="global" autoIncrement="true" dataNode="dn$1-2" />
        <table name="otherjointable" primaryKey="id" type="global" autoIncrement="true" dataNode="dn$1-2" />
    </schema>

    <dataNode name="dn1" dataHost="localhost1" database="mydb" />
    <dataNode name="dn2" dataHost="localhost2" database="mydb" />

</mycat:schema>
表名 所屬節點 切分列 切分規則
lsqtable dn$1-2 id mod-long 取模
lsqtable_supplement dn$1-2 id 繼承 ER 父類切分規則 mod-long
lsqtable_supplement_items dn$1-2 parent_id 繼承 ER 父類切分規則 mod-long
lsqtable_supplement_other dn$1-2 id 繼承 ER 父類切分規則 mod-long
wyptable dn$1-2 id

auto-sharding-long 範圍分片,但是範圍

給的很大,數據都被路由到 dn1 中

lxjtable dn$1-2 id

auto-sharding-long 範圍分片,但是範圍

給的很大,數據都被路由到 dn1 中

jointable dn$1-2 id global 全局表,路由到所有節點插入
otherjointable dn$1-2 id global 全局表,路由到所有節點插入

 

查詢條件如下:

表 lxjtable 和 wyptable 進行關聯查詢,可以查詢且可以查詢到執行計劃,因爲新添加的兩個表使用的同種切分規則,且規則一致。(多個表沒試,想使用的小夥伴可以試下)

EXPLAIN SELECT *
FROM lxjtable lxj
INNER JOIN wyptable wyp ON lxj.id = wyp.id

dn1    SELECT *   FROM lxjtable lxj   INNER JOIN wyptable wyp ON lxj.id = wyp.id
dn2    SELECT *   FROM lxjtable lxj   INNER JOIN wyptable wyp ON lxj.id = wyp.id

如果兩個不同切分規則的表進行 join 就會觸發 share join 操作,不能查出查詢計劃。如 lsqtable 和 lxjtable 兩表,無執行計劃,只有結果集。但是仍可以聯查全局表。

EXPLAIN SELECT *
FROM lxjtable lxj
INNER JOIN lsqtable lsq ON lxj.id = lsq.id

從日誌中可以看出 cat.log

INFO [$_NIOREACTOR-5-RW] (io.mycat.catlets.JoinParser.parserTable(JoinParser.java:101)) - table lsqtable Alias:lsq Hints:[]
INFO [$_NIOREACTOR-5-RW] (io.mycat.catlets.JoinParser.parser(JoinParser.java:79)) - SQL: SELECT * FROM lxjtable lxj INNER JOIN lsqtable lsq ON lxj.id = lsq.id
INFO [$_NIOREACTOR-5-RW] (io.mycat.catlets.ShareJoin.processSQL(ShareJoin.java:172)) - Catlet exec:dn1,dn2, sql:select *, id from lxjtable
INFO [$_NIOREACTOR-0-RW] (io.mycat.cache.DefaultLayedCachePool.createChildCache(DefaultLayedCachePool.java:80)) - create child Cache: mydb_LSQTABLE for layered cache TableID2DataNodeCache, size 10000, expire seconds 18000
INFO [$_NIOREACTOR-0-RW] (io.mycat.catlets.ShareJoin.createQryJob(ShareJoin.java:275)) - SQLParallJob:dn1,dn2, sql:select * from lsqtable where id in (1,2)
INFO [$_NIOREACTOR-5-RW] (io.mycat.sqlengine.EngineCtx.onJobFinished(EngineCtx.java:194)) - all job finished  for front connection: ServerConnection [id=1, schema=mydb, host=0:0:0:0:0:0:0:1, user=root,txIsolation=3, autocommit=true, schema=mydb]
INFO [$_NIOREACTOR-5-RW] (io.mycat.sqlengine.EngineCtx.writeEof(EngineCtx.java:180)) - write  eof ,packgId:13
INFO [$_NIOREACTOR-5-RW] (io.mycat.catlets.ShareJoin$1.onAllJobFinished(ShareJoin.java:189)) - 發送數據OK
INFO [$_NIOREACTOR-5-RW] (io.mycat.catlets.JoinParser.parserTable(JoinParser.java:101)) - table lsqtable Alias:lsq Hints:[]
INFO [$_NIOREACTOR-5-RW] (io.mycat.catlets.JoinParser.parser(JoinParser.java:79)) - SQL: SELECT * FROM lxjtable lxj INNER JOIN lsqtable lsq ON lxj.id = lsq.id
INFO [$_NIOREACTOR-5-RW] (io.mycat.catlets.ShareJoin.processSQL(ShareJoin.java:172)) - Catlet exec:dn1,dn2, sql:select *, id from lxjtable
INFO [$_NIOREACTOR-4-RW] (io.mycat.catlets.ShareJoin.createQryJob(ShareJoin.java:275)) - SQLParallJob:dn1,dn2, sql:select * from lsqtable where id in (1,2)
INFO [$_NIOREACTOR-0-RW] (io.mycat.sqlengine.EngineCtx.onJobFinished(EngineCtx.java:194)) - all job finished  for front connection: ServerConnection [id=1, schema=mydb, host=0:0:0:0:0:0:0:1, user=root,txIsolation=3, autocommit=true, schema=mydb]
INFO [$_NIOREACTOR-0-RW] (io.mycat.sqlengine.EngineCtx.writeEof(EngineCtx.java:180)) - write  eof ,packgId:13
INFO [$_NIOREACTOR-0-RW] (io.mycat.catlets.ShareJoin$1.onAllJobFinished(ShareJoin.java:189)) - 發送數據OK

比較重要的點:基本上就是將 A share join B 的操作,分爲兩部分左側查詢和右側查詢,左表  select *, id  右側  select * in  操作。之後根據左側的 id 替換右側的結果集,合併數據。

Catlet exec:dn1,dn2, sql:select *, id from lxjtable
SQLParallJob:dn1,dn2, sql:select * from lsqtable where id in (1,2)

且三表聯查時將發生錯誤。如下。

EXPLAIN SELECT *
FROM lxjtable lxj
INNER JOIN lsqtable lsq ON lxj.id = lsq.id
INNER JOIN wyptable wyp ON lxj.id = wyp.id

> 2013 - Lost connection to MySQL server during query
> 時間: 0.02s

但是關聯多個全局表是可以的。

其實就是,不過多少個表,只要是以相同的分片規則分在一個節點(全局表每個節點冗餘),每個分片都可以自主的進行數據關聯,之後進行合併。但是以不同分片規則的表就不一樣了。因爲相關聯的節點可能處在不同的節點中。這樣只能先按分片鍵查出第一個表的相關數據。之後使用 in 關鍵字來查第二個表。所以最好在第一個表查詢時加入 on 關鍵字來降低第一個結果集的數量。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章