mycat が水平分割を完了します
導入
垂直分割と比較して、水平分割はテーブルを分類するのではなく、特定の分野の特定のルールに従って複数のデータベースに分散し、各テーブルにはデータの一部が含まれます。簡単に言うと、データの水平分割は、図に示すように、データ行に応じた分割、つまり、テーブル内の一部の行を 1 つのデータベースに分割し、他の行を別のデータベースに分割することとして理解できます。
分割するテーブルを選択してください
MySQL の 1 つのテーブルに格納されるデータ数にはボトルネックがあり、1 つのテーブルのデータ数が 100 万件に達するとボトルネックに達し、クエリの効率に影響を及ぼし、最適化のために水平分割 (テーブル分割) が必要になります。たとえば、この例のordersとorders_detailのデータは600万行に達しており、サブテーブルによって最適化する必要があります。
テーブル セグメンテーション フィールドは、orders テーブルを例として、さまざまなフィールドに基づいてテーブルに分割できます。schema.xml
ファイルを変更し、orders テーブルのデータ ノードを dn1、dn2 として設定し、シャーディング ルールを mod_rule (カスタマイズされた名前):
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100" dataNode="dn1">
<table name="tbl_consumer" dataNode="dn2"></table>
<!-- rule:水平分表得规则名称该名称可以随便定义。-->
<table name="tbl_orders" dataNode="dn1,dn2" rule="mod_rule"></table>
</schema>
<dataNode name="dn1" dataHost="host1" database="orders" />
<dataNode name="dn2" dataHost="host2" database="consumer" />
<dataHost name="host1" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="192.168.179.131:3306" user="root"
password="123456">
</writeHost>
</dataHost>
<dataHost name="host2" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM2" url="192.168.179.132:3306" user="root"
password="123456">
</writeHost>
</dataHost>
</mycat:schema>
主な注意点:
rules.xml でルールを設定します。
<tableRule name="mod_rule">
<rule>
<columns>customer_id</columns>
<algorithm>mod-long</algorithm>
</rule>
</tableRule>
<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
<!-- 数据库的个数 -->
<property name="count">2</property>
</function>
両方のマシンに対応するデータベースがあることを確認してください (この場合: tbl_orders)
INSERT INTO tbl_orders values(1,101,100,100100);
列:パーティション テーブル、挿入には ColumnList を提供する必要があります
シャード テーブルにデータを追加するときは、列のリストを指定する必要があります。これを指定しないと、どの値がシャード テーブルのフィールドであるかを判断できません。
mycat を通じて関連データをテーブルに追加できます。
INSERT INTO tbl_orders(id,order_type,customer_id,amount) VALUES (1,101,100,100100);
INSERT INTO tbl_orders(id,order_type,customer_id,amount) VALUES(2,101,100,100300);
INSERT INTO tbl_orders(id,order_type,customer_id,amount) VALUES(3,101,101,120000);
INSERT INTO tbl_orders(id,order_type,customer_id,amount) VALUES(4,101,101,103000);
INSERT INTO tbl_orders(id,order_type,customer_id,amount) VALUES(5,102,101,100400);
INSERT INTO tbl_orders(id,order_type,customer_id,amount) VALUES(6,102,100,100020);
発見する:
144 は 192.168.179.131、145 は 192.168.179.132 画面は変わりません。
Mycatのシャーディング「結合」
結合: 結合テーブル クエリ
Orders 注文テーブルがシャード化されました。それに関連付けられているorders_detail注文詳細テーブルに対して結合クエリを実行するにはどうすればよいですか?orders_detailもシャード化する必要があります。結合の原則は次のとおりです。
ER テーブルを使用して、上記の単語テーブル関連付けクエリの問題を解決します。サブテーブルの格納場所はメインテーブルに依存します, およびそれらは物理的に互いに近くに格納されるため、JION の効率とパフォーマンスの問題が完全に解決されます。この考えに基づいて、ER 関係に基づくデータ断片化戦略が提案されます。子テーブルのレコードと関連するレコードのレコード親テーブルは次の場所に保存されます同じデータ断片優れた。
schema.xml ファイルを変更する
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100" dataNode="dn1">
<table name="tbl_consumer" dataNode="dn2"></table>
<!-- rule:水平分表得规则名称该名称可以随便定义。-->
<table name="tbl_orders" dataNode="dn1,dn2" rule="mod_rule">
<!-- childTale:定义子表得标签
name: 关联得子表名称
primaryKey:子表中得主键列名
joinKey: 子表中外键得列名
parentKey: 关联得父表得主键名称
-->
<childTable name="tbl_orders_detail" primaryKey="id" joinKey="order_id" parentKey="id"/>
</table>
</schema>
<dataNode name="dn1" dataHost="host1" database="orders" />
<dataNode name="dn2" dataHost="host2" database="orders" />
<dataHost name="host1" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="192.168.179.131:3306" user="root"
password="123456">
</writeHost>
</dataHost>
<dataHost name="host2" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM2" url="192.168.179.132:3306" user="root"
password="123456">
</writeHost>
</dataHost>
</mycat:schema>
主な注意点:
両方のマシンに tbl_orders_detail テーブルがあることを確認してください。
CREATE TABLE tbl_orders_detail(
id INT AUTO_INCREMENT,
detail VARCHAR(2000),
order_id INT,
PRIMARY KEY(id)
);
mycatを再起動します
mycat を介して tbl_orders_detail テーブルにデータを追加します。
INSERT INTO tbl_orders_detail(id,detail,order_id) values(7,'detail1',1);
INSERT INTO tbl_orders_detail(id,detail,order_id) VALUES(8,'detail1',2);
INSERT INTO tbl_orders_detail(id,detail,order_id) VALUES(9,'detail1',3);
INSERT INTO tbl_orders_detail(id,detail,order_id) VALUES(10,'detail1',4);
INSERT INTO tbl_orders_detail(id,detail,order_id) VALUES(11,'detail1',5);
INSERT INTO tbl_orders_detail(id,detail,order_id) VALUES(12,'detail1',6);
テスト
グローバルテーブル
注文データ フィールド テーブル。—保存された注文のステータス --> 支払い未払いキャンセル保留出荷出荷確認済み。。。。
各ノードに順序データディクショナリテーブルが必要なためです。そこで、データディクショナリテーブルをグローバルテーブルとして定義します。
テーブルが必要な場合は、グローバルテーブルを作成する必要があります。
- 変更は頻繁ではありません
- 全体のデータ量はあまり変わっていない
- データサイズは小さく、数十万レコードを超えることはほとんどありません
これを考慮して、Mycat では、次のような特徴を持つ「グローバル テーブル」と呼ばれる特別なテーブルを定義しています。
- グローバル テーブルの挿入および更新操作は、各シャードのデータの一貫性を維持するために、すべてのノードでリアルタイムに実行されます。
- グローバルテーブルのクエリ操作は1つのノードからのみ取得されます。
- グローバル表は任意の表とのJOINが可能であり、ディクショナリ表、またはディクショナリ表の特性を満たす一部の表をグローバル表として定義することで、データのJOINの問題を別の面から解決できます。Mycat は、ER 関係に基づくグローバル テーブル + シャーディング戦略を通じて、エンタープライズ アプリケーション開発のニーズの 80% 以上を満たすことができます。
schema.xmlを変更する
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100" dataNode="dn1">
<table name="tbl_consumer" dataNode="dn2"></table>
<!-- rule:水平分表得规则名称该名称可以随便定义。-->
<table name="tbl_orders" dataNode="dn1,dn2" rule="mod_rule">
<!-- childTale:定义子表得标签
name: 关联得子表名称
primaryKey:子表中得主键列名
joinKey: 子表中外键得列名
parentKey: 关联得父表得主键名称
-->
<childTable name="tbl_orders_detail" primaryKey="id" joinKey="order_id" parentKey="id"/>
</table>
<!-- type:global表示全局表得意思-->
<table name="tbl_dict_order_type" dataNode="dn1,dn2" type="global" ></table>
</schema>
<dataNode name="dn1" dataHost="host1" database="orders" />
<dataNode name="dn2" dataHost="host2" database="consumer" />
<dataHost name="host1" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="192.168.179.131:3306" user="root"
password="123456">
</writeHost>
</dataHost>
<dataHost name="host2" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM2" url="192.168.179.132:3306" user="root"
password="123456">
</writeHost>
</dataHost>
</mycat:schema>
主な注意点:
mycatを再起動します
両方のサーバー マシンに tbl_dict_order_type データベースがあることを確認してください。 注: mycat を通じてテーブルを作成する必要があります。
CREATE TABLE tbl_dict_order_type(
id INT AUTO_INCREMENT,
order_type VARCHAR(200),
PRIMARY KEY(id)
);
mycat 経由でデータを追加する
INSERT INTO tbl_dict_order_type(id,order_type) VALUES(101,'type1');
INSERT INTO tbl_dict_order_type(id,order_type) VALUES(102,'type2');
両方のデータベースとグローバルテーブルにデータがあります