一.什么是水平分庫
將一張表水平切分到多個庫中
1.1分片原則
- 1.需要分片的表是少數的
- 2.能不切分盡量不要切分
- 3.日志表可以采取歸檔方式
- 4.選擇合適的切分規則和分片建,確保數據分片均勻,否則依然存在性能瓶頸
- 5.盡量避免跨分片join操作,保證關聯操作表在同一分片
1.2分片后如何處理查詢
- 1.根據簡單分片規則,對分片鍵進行路由到正確的后端物理數據庫
- 2.如果不是使用分片鍵的話,將會遍歷后端數據庫,極大消耗性能
二.水平切分步驟
2.1根據業務狀態確定要進行水平切分的表
讀寫頻繁,訪問量非常大的表才需要切分,一般是訂單表
如何選擇分片鍵
- 1.盡可能的比較均勻分布數據到各個節點上,自增長主鍵並不是很好的選擇,因為不會用於查詢
- 2.業務字段是最頻繁的或者最重要的查詢條件
2.2分析業務模型選擇分片鍵及分片算法
一般分片鍵選擇的是頻繁作為查詢的字段,關鍵是能保證分片后的數據分布均勻,常用簡單取模算法
- 對訂單相關表進行水平切分
- 不僅僅是訂單表,經常與訂單表關聯查詢的表也需要一並分片,避免跨分片查詢,大表不適合作為全局表
- 訂單號,可以保證分片均勻,但是實際業務很少根據訂單號來查詢
- 下單人ID,業務查詢更多,更適合,但是分片並不均勻,但不嚴重,值得考慮
- 采用簡單取模分片算法,可以保證數據盡可能均勻
2.3適用mycat部署分片集群
- 1.使用schema.xml配置邏輯庫及邏輯表
<!-- <table name="order_master" primaryKey="order_id" dataNode="dn_orderdb" /> -->
<table name="order_master" primaryKey="order_id" dataNode="dn_orderdb01,dn_orderdb02,dn_orderdb03,dn_orderdb04" rule="order_master"/>
<!-- 只需要增加表所在的物理節點schema名稱和指定規則rule -->
<dataNode name="dn_orderdb01" dataHost="mysql10143" database="orderdb01" />
<dataNode name="dn_orderdb02" dataHost="mysql10143" database="orderdb02" />
<dataNode name="dn_orderdb03" dataHost="mysql10144" database="orderdb03" />
<dataNode name="dn_orderdb04" dataHost="mysql10144" database="orderdb04" />
- 2.使用rule.xml配置分片表的分片規則
<tableRule name="order_master">
<rule>
<columns>customer_id</columns>
<algorithm>mod-long</algorithm>
</rule>
</tableRule>
<function name="mod-long" class="org.opencloudb.route.function.PartitionByMod">
<!-- 分片算法,唯一;JAVA類路徑,1.6是"io.mycat.route.function.PartitionByMod"-->
<property name="count">4</property>
</function>
- 3.驗證
# 現在邏輯庫上進行查看,此時是沒有數據的
# 需要提前建庫建表,否則報錯表不存在
app_imooc@172.16.10.142 00:26: [imooc_db]> select * from order_master;
Empty set (0.08 sec)
# 在邏輯庫imooc_db上插入5條數據,正常是orderdb02 2條數據(節點索引順序為1),其他各1條數據
insert into order_master(order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(70001,90001,'yzw1',1,1,1,'address1',1,20);
insert into order_master(order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(70002,90002,'yzw2',2,2,2,'address1',1,20);
insert into order_master(order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(70003,90003,'yzw3',3,3,3,'address1',1,20);
insert into order_master(order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(70004,90004,'yzw4',4,4,4,'address1',1,20);
insert into order_master(order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(70005,90005,'yzw5',5,5,5,'address1',1,20);
# truncate table報錯
app_imooc@172.16.10.142 10:51: [imooc_db]> truncate table order_master;
ERROR 1105 (HY000): DROP command denied to user 'bm_mycat'@'172.16.10.142' for table 'order_master'
# 邏輯庫查看插入結果
app_imooc@172.16.10.142 10:50: [imooc_db]> select order_id,order_sn,customer_id from order_master;
+----------+----------+-------------+
| order_id | order_sn | customer_id |
+----------+----------+-------------+
| 80005 | 70002 | 90002 |
| 80005 | 70003 | 90003 |
| 80005 | 70004 | 90004 |
| 80006 | 70001 | 90001 |
| 80007 | 70005 | 90005 |
+----------+----------+-------------+
5 rows in set (0.00 sec)
# 在物理庫查看是否有這4條數據,驗證成功
root@localhost 10:52: [orderdb01]> select order_id,order_sn,customer_id from order_master;
+----------+----------+-------------+
| order_id | order_sn | customer_id |
+----------+----------+-------------+
| 80005 | 70004 | 90004 |
+----------+----------+-------------+
1 row in set (0.00 sec)
root@localhost 10:52: [orderdb02]> select order_id,order_sn,customer_id from order_master;
+----------+----------+-------------+
| order_id | order_sn | customer_id |
+----------+----------+-------------+
| 80006 | 70001 | 90001 |
| 80007 | 70005 | 90005 |
+----------+----------+-------------+
2 rows in set (0.00 sec)
root@localhost 10:05: [orderdb03]> select order_id,order_sn,customer_id from order_master;
+----------+----------+-------------+
| order_id | order_sn | customer_id |
+----------+----------+-------------+
| 80005 | 70002 | 90002 |
+----------+----------+-------------+
1 row in set (0.00 sec)
root@localhost 10:52: [orderdb04]> select order_id,order_sn,customer_id from order_master;
+----------+----------+-------------+
| order_id | order_sn | customer_id |
+----------+----------+-------------+
| 80005 | 70003 | 90003 |
+----------+----------+-------------+
1 row in set (0.00 sec)
- 4.使用server.xml配置訪問權限
#配置用戶登錄
2.4測試分片集群,采用應用端雙寫方式進行
2.5業務及數據遷移
三.全局自增ID
- 分片表中的自增ID在邏輯表中有重復
- 第三方給ID或者使用mycat自增ID
3.1全局自增ID方法
- 1.本地文件方式:適用服務器本地磁盤的方式
- 2.數據庫方式:適用數據庫存儲的方式
- 3.本地時間戳方式:適用時間戳
- 4.分布式zookeeper生成ID
3.2本地文件全局ID
- 優點:本地加載,讀取速度快,配置簡單
- 缺點:集群部署無法使用,不同的mycat無法保證id唯一,使mycat變成了有狀態的中間件
配置方法
- 1.server.xml增加屬性
<property name="sequnceHandlerType>0</property>
- 2.sequence_conf.properties配置
#default global sequence
GLOBAL.HISIDS=
GLOBAL.MINID=10001
GLOBAL.MAXID=20000
GLOBAL.CURID=10000
# self define sequence
ORDER_MASTER.HISIDS=
ORDER_MASTER.MINID=1001
ORDER_MASTER.MAXID=2000
ORDER_MASTER.CURID=1000
# 以上配置文件中,自定義表名必須大寫書寫HISIDS:表示使用過的歷史分段(一般無特殊需要可不配置)
# MINID :最小ID 值
# MAXID :表示最大ID 值
# CURID :表示當前ID 值。
# 當 sequence_conf.properties的配置名字與 表名一致的時候sql可以不包含ID字段(此處表名為id_local_file),邏輯表需要增加屬性autoIncrement="true"
- 3.插入數據
# mycat restart
# delete from order_master;
insert into order_master(order_id,order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(next value for MYCATSEQ_GLOBAL,70001,90001,'yzw1',1,1,1,'address1',1,20);
insert into order_master(order_id,order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(next value for MYCATSEQ_GLOBAL,70002,90002,'yzw2',2,2,2,'address1',1,20);
insert into order_master(order_id,order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(next value for MYCATSEQ_GLOBAL,70003,90003,'yzw3',3,3,3,'address1',1,20);
insert into order_master(order_id,order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(next value for MYCATSEQ_GLOBAL,70004,90004,'yzw4',4,4,4,'address1',1,20);
insert into order_master(order_id,order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(next value for MYCATSEQ_GLOBAL,70005,90005,'yzw5',5,5,5,'address1',1,20);
# 此時邏輯表中的order_id唯一
app_imooc@172.16.10.142 11:35: [imooc_db]> select order_id,order_sn,customer_id from order_master;
+----------+----------+-------------+
| order_id | order_sn | customer_id |
+----------+----------+-------------+
| 10004 | 70004 | 90004 |
| 10003 | 70003 | 90003 |
| 10001 | 70001 | 90001 |
| 10005 | 70005 | 90005 |
| 10002 | 70002 | 90002 |
+----------+----------+-------------+
5 rows in set (0.01 sec)
insert into order_master(order_id,order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(next value for MYCATSEQ_ORDER_MASTER,70001,90001,'yzw1',1,1,1,'address1',1,20);
insert into order_master(order_id,order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(next value for MYCATSEQ_ORDER_MASTER,70002,90002,'yzw2',2,2,2,'address1',1,20);
insert into order_master(order_id,order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(next value for MYCATSEQ_ORDER_MASTER,70003,90003,'yzw3',3,3,3,'address1',1,20);
insert into order_master(order_id,order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(next value for MYCATSEQ_ORDER_MASTER,70004,90004,'yzw4',4,4,4,'address1',1,20);
insert into order_master(order_id,order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(next value for MYCATSEQ_ORDER_MASTER,70005,90005,'yzw5',5,5,5,'address1',1,20);
# 此時邏輯表中的order_id依然是唯一,但是ID值使用的是自定義表自增屬性的值
app_imooc@172.16.10.142 11:48: [imooc_db]> select order_id,order_sn,customer_id from order_master;
+----------+----------+-------------+
| order_id | order_sn | customer_id |
+----------+----------+-------------+
| 1009 | 70003 | 90003 |
| 1008 | 70002 | 90002 |
| 1007 | 70001 | 90001 |
| 1011 | 70005 | 90005 |
| 1010 | 70004 | 90004 |
+----------+----------+-------------+
5 rows in set (0.00 sec)
# 不指定自增字段插入
# 邏輯表必須增加自增屬性,否則不指定自增字段插入則使用分片表本身自增id
#<table name="order_master" primaryKey="order_id" autoIncrement="true" dataNode="dn_orderdb01,dn_orderdb02,dn_orderdb03,dn_orderdb04" rule="order_master"/>
insert into order_master(order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(70001,90001,'yzw1',1,1,1,'address1',1,20);
insert into order_master(order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(70002,90002,'yzw2',2,2,2,'address1',1,20);
insert into order_master(order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(70003,90003,'yzw3',3,3,3,'address1',1,20);
insert into order_master(order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(70004,90004,'yzw4',4,4,4,'address1',1,20);
insert into order_master(order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(70005,90005,'yzw5',5,5,5,'address1',1,20);
app_imooc@172.16.10.142 11:58: [imooc_db]> select order_id,order_sn,customer_id from order_master;
+----------+----------+-------------+
| order_id | order_sn | customer_id |
+----------+----------+-------------+
| 1001 | 70001 | 90001 |
| 1005 | 70005 | 90005 |
| 1003 | 70003 | 90003 |
| 1004 | 70004 | 90004 |
| 1002 | 70002 | 90002 |
+----------+----------+-------------+
5 rows in set (0.01 sec)
3.3數據庫方式
- 優點:mycat重啟后,sequence值不會被初始化,因為從數據庫中取,每次取完按自增步長增加
- 缺點:sequence數據庫主從切換后,存在mycat適用緩存序列號,可能存在ID重復風險,可以手動增加步長避免
配置方法
- 1.server.xml增加屬性
<property name="sequnceHandlerType">1</property>
- 2.sequence_db_conf.properties
#sequence stored in datanode
GLOBAL=dn_test
ORDER_MASTER=dn_test
datanode必須要mycat能訪問的數據庫,並不一定需要在分片表的數據庫中
- 3.schema.xml增加主機節點和數據節點,讓mycat能訪問上面配置的數據節點
- 4.在對應節點的數據庫中增加函數和表,用戶必須授予表、函數、存儲過程的訪問權限
# 需要全局ID的表明需要寫入表中,大寫
INSERT INTO mycat_sequence values('ORDER_MASTER', 1, 100);
root@master 11:48: [test]> select * from mycat_sequence;
+--------------+---------------+-----------+
| NAME | current_value | increment |
+--------------+---------------+-----------+
| GLOBAL | 100000 | 100 |
| ORDER_MASTER | 1 | 100 |
+--------------+---------------+-----------+
2 rows in set (0.00 sec)
- 5.schema.xml增加配置,適用全局自增ID
autoIncrement="true"
<table name="order_master" primaryKey="order_id" autoIncrement="true" dataNode="dn_orderdb01,dn_orderdb02,dn_orderdb03,dn_orderdb04" rule="order_master"/>
- 6.在邏輯庫中插入數據
# 適用ID表里面的全局ID插入
insert into order_master(order_id,order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(next value for MYCATSEQ_GLOBAL,70001,90001,'yzw1',1,1,1,'address1',1,20);
insert into order_master(order_id,order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(next value for MYCATSEQ_GLOBAL,70002,90002,'yzw2',2,2,2,'address1',1,20);
insert into order_master(order_id,order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(next value for MYCATSEQ_GLOBAL,70003,90003,'yzw3',3,3,3,'address1',1,20);
insert into order_master(order_id,order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(next value for MYCATSEQ_GLOBAL,70004,90004,'yzw4',4,4,4,'address1',1,20);
insert into order_master(order_id,order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(next value for MYCATSEQ_GLOBAL,70005,90005,'yzw5',5,5,5,'address1',1,20);
# 使用ID表里面的對應表ID插入
insert into order_master(order_id,order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(next value for MYCATSEQ_ORDER_MASTER,70001,90001,'yzw1',1,1,1,'address1',1,20);
insert into order_master(order_id,order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(next value for MYCATSEQ_ORDER_MASTER,70002,90002,'yzw2',2,2,2,'address1',1,20);
insert into order_master(order_id,order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(next value for MYCATSEQ_ORDER_MASTER,70003,90003,'yzw3',3,3,3,'address1',1,20);
insert into order_master(order_id,order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(next value for MYCATSEQ_ORDER_MASTER,70004,90004,'yzw4',4,4,4,'address1',1,20);
insert into order_master(order_id,order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(next value for MYCATSEQ_ORDER_MASTER,70005,90005,'yzw5',5,5,5,'address1',1,20);
# 不指定id列,效果同上
insert into order_master(order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(70001,90001,'yzw1',1,1,1,'address1',1,20);
insert into order_master(order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(70002,90002,'yzw2',2,2,2,'address1',1,20);
insert into order_master(order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(70003,90003,'yzw3',3,3,3,'address1',1,20);
insert into order_master(order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(70004,90004,'yzw4',4,4,4,'address1',1,20);
insert into order_master(order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(70005,90005,'yzw5',5,5,5,'address1',1,20);
3.4本地時間戳方式
ID= 64 位二進制 (42(毫秒)+5(機器 ID)+5(業務編碼)+12(重復累加)
- 優點:與mycat無關,跟時間有關系
- 缺點:字段最大長度必須大於等於18,int無法滿足
配置方法
- 1.server.xml增加屬性
<property name="sequnceHandlerType">2</property>
- 2.sequence_time_conf.properties
#sequence depend on TIME
WORKID=01
DATAACENTERID=01
# 0-31任意整數
- 3.在對應節點的數據庫中增加函數和表,用戶必須授予表、函數、存儲過程的訪問權限
# 需要全局ID的表明需要寫入表中,大寫
INSERT INTO mycat_sequence values('ORDER_MASTER', 1, 100);
root@master 11:48: [test]> select * from mycat_sequence;
+--------------+---------------+-----------+
| NAME | current_value | increment |
+--------------+---------------+-----------+
| GLOBAL | 100000 | 100 |
| ORDER_MASTER | 1 | 100 |
+--------------+---------------+-----------+
2 rows in set (0.00 sec)
- 5.schema.xml增加配置,適用全局自增ID
autoIncrement="true"
<table name="order_master" primaryKey="order_id" autoIncrement="true" dataNode="dn_orderdb01,dn_orderdb02,dn_orderdb03,dn_orderdb04" rule="order_master"/>
- 6.在邏輯庫中插入數據
# int無法滿足
ERROR 1264 (22003): Out of range value for column 'order_id' at row
app_imooc@172.16.10.142 12:32: [imooc_db]> select next value for MYCATSEQ_ORDER_MASTER;
+---------------------+
| 1025962766269288448 |
+---------------------+
| 1025962766269288448 |
+---------------------+
1 row in set (0.00 sec)
app_imooc@172.16.10.142 12:32: [imooc_db]> select next value for MYCATSEQ_GLOBAL;
+---------------------+
| 1025962827724230656 |
+---------------------+
| 1025962827724230656 |
+---------------------+
1 row in set (0.00 sec)
1
# 適用ID表里面的全局ID插入
insert into order_master(order_id,order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(next value for MYCATSEQ_GLOBAL,70001,90001,'yzw1',1,1,1,'address1',1,20);
insert into order_master(order_id,order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(next value for MYCATSEQ_GLOBAL,70002,90002,'yzw2',2,2,2,'address1',1,20);
insert into order_master(order_id,order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(next value for MYCATSEQ_GLOBAL,70003,90003,'yzw3',3,3,3,'address1',1,20);
insert into order_master(order_id,order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(next value for MYCATSEQ_GLOBAL,70004,90004,'yzw4',4,4,4,'address1',1,20);
insert into order_master(order_id,order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(next value for MYCATSEQ_GLOBAL,70005,90005,'yzw5',5,5,5,'address1',1,20);
# 使用ID表里面的對應表ID插入
insert into order_master(order_id,order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(next value for MYCATSEQ_ORDER_MASTER,70001,90001,'yzw1',1,1,1,'address1',1,20);
insert into order_master(order_id,order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(next value for MYCATSEQ_ORDER_MASTER,70002,90002,'yzw2',2,2,2,'address1',1,20);
insert into order_master(order_id,order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(next value for MYCATSEQ_ORDER_MASTER,70003,90003,'yzw3',3,3,3,'address1',1,20);
insert into order_master(order_id,order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(next value for MYCATSEQ_ORDER_MASTER,70004,90004,'yzw4',4,4,4,'address1',1,20);
insert into order_master(order_id,order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(next value for MYCATSEQ_ORDER_MASTER,70005,90005,'yzw5',5,5,5,'address1',1,20);
# 不指定id列,效果同上
insert into order_master(order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(70001,90001,'yzw1',1,1,1,'address1',1,20);
insert into order_master(order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(70002,90002,'yzw2',2,2,2,'address1',1,20);
insert into order_master(order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(70003,90003,'yzw3',3,3,3,'address1',1,20);
insert into order_master(order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(70004,90004,'yzw4',4,4,4,'address1',1,20);
insert into order_master(order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(70005,90005,'yzw5',5,5,5,'address1',1,20);
select order_id,order_sn,customer_id from order_master;
3.5分布式zookeeper生成ID 未測試,1.5沒有默認配置文件
基於ZK 與本地配置的分布式ID 生成器(可以通過ZK 獲取集群(機房)唯一InstanceID,也可以通過配置文件配置InstanceID)ID 結構:long 64 位,ID 最大可占63 位
current time millis(微秒時間戳38 位,可以使用17 年)
instanceId(實例ID,可以通過ZK 或者配置文件獲取,5 位,也就是十進制0-31)
threadId(線程ID,9 位)
increment(自增,6 位)
一共63 位,可以承受單機房單機器單線程1000*(2^6)=640000 的並發。
- 優點:無悲觀鎖,無強競爭,吞吐量更高
- 缺點:對zookeeper集群的要求增加。
配置方法
- 1.server.xml增加屬性
<property name="sequnceHandlerType">3</property>
- 2.sequence_distributed_conf.properties
INSTANCEID=01
CLUSTERID=01
- 3.在對應節點的數據庫中增加函數和表,用戶必須授予表、函數、存儲過程的訪問權限
# 需要全局ID的表明需要寫入表中,大寫
INSERT INTO mycat_sequence values('ORDER_MASTER', 1, 100);
root@master 11:48: [test]> select * from mycat_sequence;
+--------------+---------------+-----------+
| NAME | current_value | increment |
+--------------+---------------+-----------+
| GLOBAL | 100000 | 100 |
| ORDER_MASTER | 1 | 100 |
+--------------+---------------+-----------+
2 rows in set (0.00 sec)
- 5.schema.xml增加配置,適用全局自增ID
autoIncrement="true"
<table name="order_master" primaryKey="order_id" autoIncrement="true" dataNode="dn_orderdb01,dn_orderdb02,dn_orderdb03,dn_orderdb04" rule="order_master"/>
- 6.在邏輯庫中插入數據
四.ER關系
- 跨分片查詢存在跨節點問題
app_imooc@172.16.10.142 13:55: [imooc_db]> select * from order_master m join order_detail o on m.order_id=o.order_id;
ERROR 1064 (HY000): invalid route in sql, multi tables found but datanode has no intersection sql:select * from order_master m join order_detail o on m.order_id=o.order_id
- 根據ER關系,也需要對order_detail這張表進行分片
4.1配置步驟
- 1.在原先order_master所在4個分配數據庫(orderdb01/02/03/04)中建立order_detail表結構
CREATE TABLE `order_detail` (
`order_detail_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主鍵ID,訂單詳情表ID',
`order_id` int(10) unsigned NOT NULL COMMENT '訂單表ID',
`product_id` int(10) unsigned NOT NULL COMMENT '訂單商品ID',
`product_name` varchar(50) NOT NULL COMMENT '商品名稱',
`product_cnt` int(11) NOT NULL DEFAULT '1' COMMENT '購買商品數量',
`product_price` decimal(8,2) NOT NULL COMMENT '購買商品單價',
`average_cost` decimal(8,2) NOT NULL DEFAULT '0.00' COMMENT '平均成本價格',
`weight` float DEFAULT NULL COMMENT '商品重量',
`fee_money` decimal(8,2) NOT NULL DEFAULT '0.00' COMMENT '優惠分攤金額',
`w_id` int(10) unsigned NOT NULL COMMENT '倉庫ID',
`modified_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改時間',
PRIMARY KEY (`order_detail_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='訂單詳情表';
- 2.schema.xml將全局分片表進行ER分片,在父表中增加子表信息
<table name="order_master" primaryKey="order_id" autoIncrement="true" dataNode="dn_orderdb01,dn_orderdb02,dn_orderdb03,dn_orderdb04" rule="order_master">
<childTable name="order_detail" primaryKey="order_detail_id" joinKey="order_id" parentKey="order_id" autoIncrement="true" />
<!-- 指定關聯子表的表名、主鍵,及父表關聯key、父表的主鍵,同時也需要指定全局ID -->
</table>
- 3.配置表order_detail全局自增ID(使用數據庫方式)
# server.xml
# sequence_db_conf.properties增加order_detail自增ID
#sequence stored in datanode
GLOBAL=dn_test
ORDER_MASTER=dn_test
ORDER_DETAIL=dn_test
# 數據庫中增加分片表信息
insert into mycat_sequence values('ORDER_DETAIL',1,1);
- 4.插入數據
# 先插入order_master
insert into order_master(order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(70001,90001,'yzw1',1,1,1,'address1',1,20);
insert into order_master(order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(70002,90002,'yzw2',2,2,2,'address1',1,20);
insert into order_master(order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(70003,90003,'yzw3',3,3,3,'address1',1,20);
insert into order_master(order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(70004,90004,'yzw4',4,4,4,'address1',1,20);
insert into order_master(order_sn,customer_id,shipping_user,province,city,district,address,payment_method,order_money) values(70005,90005,'yzw5',5,5,5,'address1',1,20);
app_imooc@172.16.10.142 14:46: [imooc_db]> select order_sn,customer_id,order_id from order_master;
+----------+-------------+----------+
| order_sn | customer_id | order_id |
+----------+-------------+----------+
| 70005 | 90005 | 5 |
| 70001 | 90001 | 6 |
| 70005 | 90005 | 10 |
| 70004 | 90004 | 4 |
| 70004 | 90004 | 9 |
| 70003 | 90003 | 3 |
| 70003 | 90003 | 8 |
| 70002 | 90002 | 2 |
| 70002 | 90002 | 7 |
+----------+-------------+----------+
9 rows in set (0.00 sec)
# 根據order_id插入order_detail
insert into order_detail(order_detail_id,order_id,product_id,product_name,product_cnt,product_price,average_cost,weight,fee_money,w_id) values(next value for MYCATSEQ_ORDER_DETAIL,2,12,'商品2',1,22.2,12,1,10,2);
insert into order_detail(order_detail_id,order_id,product_id,product_name,product_cnt,product_price,average_cost,weight,fee_money,w_id) values(next value for MYCATSEQ_ORDER_DETAIL,3,13,'商品3',1,22.2,12,1,10,2);
insert into order_detail(order_detail_id,order_id,product_id,product_name,product_cnt,product_price,average_cost,weight,fee_money,w_id) values(next value for MYCATSEQ_ORDER_DETAIL,4,14,'商品4',1,22.2,12,1,10,2);
insert into order_detail(order_detail_id,order_id,product_id,product_name,product_cnt,product_price,average_cost,weight,fee_money,w_id) values(next value for MYCATSEQ_ORDER_DETAIL,5,15,'商品5',1,22.2,12,1,10,2);
insert into order_detail(order_detail_id,order_id,product_id,product_name,product_cnt,product_price,average_cost,weight,fee_money,w_id) values(next value for MYCATSEQ_ORDER_DETAIL,6,16,'商品6',1,22.2,12,1,10,2);
insert into order_detail(order_detail_id,order_id,product_id,product_name,product_cnt,product_price,average_cost,weight,fee_money,w_id) values(next value for MYCATSEQ_ORDER_DETAIL,7,17,'商品7',1,22.2,12,1,10,2);
insert into order_detail(order_detail_id,order_id,product_id,product_name,product_cnt,product_price,average_cost,weight,fee_money,w_id) values(next value for MYCATSEQ_ORDER_DETAIL,8,18,'商品8',1,22.2,12,1,10,2);
insert into order_detail(order_detail_id,order_id,product_id,product_name,product_cnt,product_price,average_cost,weight,fee_money,w_id) values(next value for MYCATSEQ_ORDER_DETAIL,9,19,'商品9',1,22.2,12,1,10,2);
insert into order_detail(order_detail_id,order_id,product_id,product_name,product_cnt,product_price,average_cost,weight,fee_money,w_id) values(next value for MYCATSEQ_ORDER_DETAIL,10,20,'商品10',1,22.2,12,1,10,2);
insert into order_detail(order_detail_id,order_id,product_id,product_name,product_cnt,product_price,average_cost,weight,fee_money,w_id) values(next value for MYCATSEQ_ORDER_DETAIL,5,21,'商品11',1,22.2,12,1,10,2);
insert into order_detail(order_detail_id,order_id,product_id,product_name,product_cnt,product_price,average_cost,weight,fee_money,w_id) values(next value for MYCATSEQ_ORDER_DETAIL,6,12,'商品2',1,22.2,12,1,10,2);
insert into order_detail(order_detail_id,order_id,product_id,product_name,product_cnt,product_price,average_cost,weight,fee_money,w_id) values(next value for MYCATSEQ_ORDER_DETAIL,8,12,'商品2',1,22.2,12,1,10,2);
insert into order_detail(order_detail_id,order_id,product_id,product_name,product_cnt,product_price,average_cost,weight,fee_money,w_id) values(next value for MYCATSEQ_ORDER_DETAIL,8,12,'商品2',1,22.2,12,1,10,2);
- 5.此時再進行分片關聯查詢驗證數據
select m.order_id,o.order_detail_id,o.product_id,o.product_name from order_master m join order_detail o on m.order_id=o.order_id;
+----------+-----------------+------------+--------------+
| order_id | order_detail_id | product_id | product_name |
+----------+-----------------+------------+--------------+
| 3 | 4 | 13 | 商品3 |
| 8 | 9 | 18 | 商品8 |
| 8 | 14 | 12 | 商品2 |
| 8 | 15 | 12 | 商品2 |
| 2 | 3 | 12 | 商品2 |
| 7 | 8 | 17 | 商品7 |
| 4 | 5 | 14 | 商品4 |
| 9 | 10 | 19 | 商品9 |
| 5 | 6 | 15 | 商品5 |
| 6 | 7 | 16 | 商品6 |
| 10 | 11 | 20 | 商品10 |
| 5 | 12 | 21 | 商品11 |
| 6 | 13 | 12 | 商品2 |
+----------+-----------------+------------+--------------+
13 rows in set (0.00 sec)
- 6.在其中一個分片上可以驗證,order_id一致的表落在同一個分片
root@localhost 15:05: [orderdb02]> select order_sn,customer_id,order_id,mod(customer_id,4) from order_master;
+----------+-------------+----------+
| order_sn | customer_id | order_id |
+----------+-------------+----------+
| 70005 | 90005 | 5 |
| 70001 | 90001 | 6 |
| 70005 | 90005 | 10 |
+----------+-------------+----------+
3 rows in set (0.00 sec)
root@localhost 15:06: [orderdb02]> select order_detail_id,product_id,order_id from order_detail;
+-----------------+------------+----------+
| order_detail_id | product_id | order_id |
+-----------------+------------+----------+
| 6 | 15 | 5 |
| 7 | 16 | 6 |
| 11 | 20 | 10 |
| 12 | 21 | 5 |
| 13 | 12 | 6 |
+-----------------+------------+----------+
5 rows in set (0.00 sec)