目录
零:分片表实操
ShareJoin 是一个简单的跨分片 Join,目前支持 2 个表的 join,原理就是解析 SQL 语句,拆分成单表的 SQL 语句执行,然后把各个节点的数据汇集。有限制,不同分盘规则最多两表操作
受限制的原因主要在于:各表的分片后的数据可能不在同一个分片中。所以会导致问题。
特殊情况:多个表使用同一种分片规则,且分片规则属性相同。在 share join 可以支持多与两表的查询。以下是测试样例:
schemel.xml,注意点就是我添加了两个范围分片的表 wyptable lxjtable
表名 | 所属节点 | 切分列 | 切分规则 |
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 关键字来降低第一个结果集的数量。