在這裡,構造了兩張表,熟悉Oracle的童鞋都知道,dept(部門表)和emp(員工表),其中dept中的deptno是emp表中dept_no的外鍵。 兩表的建表語句如下: create table dept(deptno int,dname varchar(10),datanode varcha
在這裡,構造了兩張表,熟悉Oracle的童鞋都知道,dept(部門表)和emp(員工表),其中dept中的deptno是emp表中dept_no的外鍵。
兩表的建表語句如下:
create table dept(deptno int,dname varchar(10),datanode varchar(10));
create table emp(empno int,dept_no int,datanode varchar(10));
註意:在這裡,最後一列都是datanode,通過插入database()函數可以很直觀的獲取插入的節點名,從而驗證分片的效果。
分別測試以下兩種情況:
1. 父表按照主鍵ID分片,子表的分片欄位與主表ID關聯,配置為ER分片
2. 父表的分片欄位為其他欄位,子表的分片欄位與主表ID關聯,配置為ER分片
首先測試第一種情況,在這裡,dept表作為父表,主鍵是deptno,empno為子表,關聯欄位為dept_no,分片欄位為deptno。
schema.xml中的配置如下:
<table name="dept" primaryKey="deptno" dataNode="dn1,dn2,dn3" rule="sharding-by-intfile"> <childTable name="emp" primaryKey="empno" joinKey="dept_no" parentKey="deptno"> </childTable> </table>
rule.xml中的配置如下:
<tableRule name="sharding-by-intfile"> <rule> <columns>deptno</columns> <algorithm>hash-int</algorithm> </rule> </tableRule>
修改很簡單,就是將原來的id修改為deptno,代表分片的欄位
partition-hash-int.txt的值修改為:
10=0
20=1
驗證如下:
插入父表的值,
datanode為db1,與partition-hash-int.txt中的配置相符
mysql> insert into dept(deptno,dname,datanode) values(10,'ACCOUNTING',database()); Query OK, 1 row affected (0.05 sec) mysql> select * from dept; +--------+------------+----------+ | deptno | dname | datanode | +--------+------------+----------+ | 10 | ACCOUNTING | db1 | +--------+------------+----------+ 1 row in set (0.12 sec)
日誌輸出信息如下:
接下來插入子表的值
mysql> insert into emp(empno,dept_no,datanode) values(7788,10,database()); Query OK, 1 row affected (0.01 sec)
日誌輸出信息如下:
關鍵點在於“using parent partion rule directly”。意思是直接使用父的分片規則。如果表本身並沒有指定外鍵約束。
則即便父並沒有相應的主鍵值,子表依舊可以插入,只要分片規則中有所定義。
如下所示:
mysql> select * from emp; +-------+---------+----------+ | empno | dept_no | datanode | +-------+---------+----------+ | 7788 | 10 | db1 | +-------+---------+----------+ 1 row in set (0.52 sec) mysql> select * from dept; +--------+------------+----------+ | deptno | dname | datanode | +--------+------------+----------+ | 10 | ACCOUNTING | db1 | +--------+------------+----------+ 1 row in set (0.13 sec) mysql> insert into emp(empno,dept_no,datanode) values(1234,20,database()); Query OK, 1 row affected (0.09 sec)
儘管dept中沒有deptno為20的行。
但emp還是能插入dept_no為20的值
日誌的輸出信息如下:
所以,對於第一種情況,即父表按照主鍵分片,字表的分片欄位與主表關聯,結論就是,子表進行insert操作時,並不會檢查父表中是否有相關的主鍵(對於子表的外鍵),而是直接根據分片規則進行判斷。
如果分片規則中沒有定義,則會報如下錯誤:
mysql> insert into emp(empno,dept_no,datanode) values(1234,30,database()); ERROR 1064 (HY000): can't find datanode for sharding column:DEPTNO val:30
2. 父表的分片欄位為其他欄位,子表的分片欄位與主表ID關聯,配置為ER分片
在這裡,打算用dname作為分片欄位,這樣的話,只需要修改route.xml和partition-hash-int.txt了。
首先,修改rule.xml
<tableRule name="sharding-by-intfile"> <rule> <columns>dname</columns> <algorithm>hash-int</algorithm> </rule> </tableRule>
<function name="hash-int" class="org.opencloudb.route.function.PartitionByFileMap"> <property name="mapFile">partition-hash-int.txt</property> <property name="type">1</property> </function>
因dname是字元類型,故將type設置為1。
接著,修改演算法配置文件的值
[root@mysql-server1 conf]# cat partition-hash-int.txt accounting,research=0 sales=1 operations=2
登錄mycat管理埠,重新載入配置文件
[root@mysql-server1 conf]# mysql -h192.168.244.145 -utest -ptest -P9066
mysql> reload @@config; Query OK, 1 row affected (0.14 sec) Reload config success
現在進行測試:
mysql> insert into dept(deptno,dname,datanode) values(10,'accounting',database()); Query OK, 1 row affected (0.14 sec) mysql> insert into emp(empno,dept_no,datanode) values(1234,10,database()); Query OK, 1 row affected (0.29 sec)
日誌的輸出信息如下:
插入第二個分區中的值
mysql> insert into dept(deptno,dname,datanode) values(20,'sales',database()); Query OK, 1 row affected (0.01 sec) mysql> insert into emp(empno,dept_no,datanode) values(1234,20,database()); Query OK, 1 row affected (0.41 sec)
日誌的輸出信息如下:
這次是在兩個分區查找子表的分區節點
插入第三個分區中的值
mysql> insert into dept(deptno,dname,datanode) values(30,'operations',database()); Query OK, 1 row affected (0.00 sec) mysql> insert into emp(empno,dept_no,datanode) values(4567,30,database()); Query OK, 1 row affected (0.62 sec)
日誌的輸出信息如下:
在三個分區中查找子表的分區節點
總結:在父表的分片欄位為其他欄位,子表的分片欄位與主表ID關聯這種情況下,子表的分區節點是順序查找的,在該例中,依次從dn1,dn2和dn3中查找,如果dn1中存在,就直接插入到dn1中,反之,則繼續查找dn2節點,如果仍不存在,則繼續在dn3節點中查找。