按日期分片是時間序列數據(訂單、日誌、監控指標)最常用的分片策略。MyCat 內建 PartitionByDate 算法,支援按天、月、年等時間粒度將數據均勻分布到不同分片。本文以「從 2016-01-01 起,每 10 天一個分片」為例,完整演示配置、建表、寫入、查詢路由與日誌分析。
sBeginDate=2016-01-01sPartionDay=10(每 10 天一個分片)分片號 = floor((目標日期 - 起始日期).days / 10)<function name="sharding-by-date" class="org.opencloudb.route.function.PartitionByDate">
<property name="dateFormat">yyyy-MM-dd</property>
<property name="sBeginDate">2016-01-01</property>
<property name="sPartionDay">10</property>
</function>
<tablerule name="sharding-by-date-tr04">
<rule>
<columns>CREATE_TIME</columns>
<algorithm>sharding-by-date</algorithm>
</rule>
</tablerule>
<table name="ORDER0402" rule="sharding-by-date-tr04"/>
CREATE TABLE ORDER0402(
ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
PROVINCE VARCHAR(16),
SN VARCHAR(64),
CREATE_TIME DATETIME
);
-- 2016-01-03 屬於第 0 個 10 天區間 → dn21
INSERT INTO ORDER0402(ID,PROVINCE,SN,CREATE_TIME)
VALUES(10001,'shanghai','shanghai10006_2016-01-03','2016-01-03');
-- 2016-01-13 屬於第 1 個 10 天區間 → dn22
INSERT INTO ORDER0402(ID,PROVINCE,SN,CREATE_TIME)
VALUES(5000001,'shanghai','shanghai10006_2016-01-13','2016-01-13');
mysql> EXPLAIN INSERT ... VALUES(10001,...,'2016-01-03');
+-----------+--------------------------------------------------+
| DATA_NODE | SQL |
+-----------+--------------------------------------------------+
| dn21 | INSERT ... VALUES(10001,...,'2016-01-03') |
+-----------+--------------------------------------------------+
mysql> EXPLAIN INSERT ... VALUES(5000001,...,'2016-01-13');
+-----------+--------------------------------------------------+
| DATA_NODE | SQL |
+-----------+--------------------------------------------------+
| dn22 | INSERT ... VALUES(5000001,...,'2016-01-13') |
+-----------+--------------------------------------------------+
關鍵節點(以 2016-01-13 寫入為例):
ServerConnection INSERT ... CREATE_TIME='2016-01-13'route={ 1 -> dn22{INSERT ...} } 直接命中 dn22NonBlockingSession release connection MySQLConnection[id=17, host=13.23.1.11, port=3327, attachment=dn22{...}]PhysicalDatasource release channel ... modifiedSQLExecuted=false日期分片同樣屬於單點直連路由,無緩存構建開銷。
mysql> EXPLAIN SELECT * FROM ORDER0402 WHERE CREATE_TIME='2016-01-03';
+-----------+--------------------------------------------------+
| DATA_NODE | SQL |
+-----------+--------------------------------------------------+
| dn21 | SELECT * FROM ORDER0402 WHERE CREATE_TIME='2016-01-03' LIMIT 100 |
+-----------+--------------------------------------------------+
日誌:SQLRouteCache add cache ... route={ 1 -> dn21{...} }
mysql> EXPLAIN SELECT * FROM ORDER0402 WHERE CREATE_TIME<'2016-01-04';
+-----------+--------------------------------------------------+
| DATA_NODE | SQL |
+-----------+--------------------------------------------------+
| dn21 | SELECT * FROM ORDER0402 WHERE CREATE_TIME<'2016-01-04' LIMIT 100 |
| dn22 | SELECT * FROM ORDER0402 WHERE CREATE_TIME<'2016-01-04' LIMIT 100 |
+-----------+--------------------------------------------------+
即使數據僅在 dn21,範圍條件導致廣播查詢。
mysql> EXPLAIN SELECT * FROM ORDER0402 WHERE SN='shanghai10006_2016-01-03';
+-----------+--------------------------------------------------+
| DATA_NODE | SQL |
+-----------+--------------------------------------------------+
| dn21 | SELECT * FROM ORDER0402 WHERE SN='shanghai10006_2016-01-03' LIMIT 100 |
| dn22 | SELECT * FROM ORDER0402 WHERE SN='shanghai10006_2016-01-03' LIMIT 100 |
+-----------+--------------------------------------------------+
schema.xml 定義足夠的 dataNode。