彻底分清:垂直分库、水平分库、垂直分表、水平分表(附 Mycat 完整配置)

发布时间:2026/7/10 22:37:34
彻底分清:垂直分库、水平分库、垂直分表、水平分表(附 Mycat 完整配置) Mycat 分库分表配置详解垂直/水平 分库/分表 一网打尽Mycat 作为经典的数据库中间件其核心功能就是对数据进行分片而分片又常被划分为四种典型策略垂直分库、水平分库、垂直分表、水平分表。很多人在配置时对rule的写法、分片键的位置、多表规则能否复用等问题感到困惑。本文将用最清晰的配置示例和总结一次性讲透这四种方式并给出可直接套用的模板。本文基于 Mycat 1.6 版本配置均以schema.xml和rule.xml为例。0. 公共基础结构在开始之前先给出 Mycat 的schema.xml基本骨架后面的所有配置都将基于此展开?xml version1.0?!DOCTYPE mycat:schema SYSTEM schema.dtdmycat:schema xmlns:mycathttp://io.mycat/!-- 逻辑库 --schema nameMYCAT_DB checkSQLschemafalse sqlMaxLimit100!-- 各种 table 配置放在这里 --/schema!-- 数据节点逻辑库 → 物理库 --dataNode namedn1 dataHosthost1 databasedb1 /dataNode namedn2 dataHosthost2 databasedb2 /dataNode namedn3 dataHosthost3 databasedb3 /!-- 物理主机配置示例仅写一个实际可扩展 --dataHost namehost1 maxCon1000 minCon10balance0 writeType0 dbTypemysql dbDrivernativeheartbeatselect user()/heartbeatwriteHost hosthostM1 url127.0.0.1:3306 userroot password123456//dataHost!-- host2、host3 配置类似略 --/mycat:schemarule.xml的基本结构?xml version1.0?!DOCTYPE mycat:rule SYSTEM rule.dtdmycat:rule xmlns:mycathttp://io.mycat/!-- 这里放 tableRule 和 function --/mycat:rule1. 垂直分库按业务分库整表迁移特点不同业务表放在不同的数据库节点上不涉及数据行的拆分不需要配置分片规则rule。场景用户表、订单表、商品表分别存入不同的物理库。schema.xml 配置schema nameMYCAT_DB checkSQLschemafalse sqlMaxLimit100!-- 用户模块放在 dn1 --table namet_user dataNodedn1 primaryKeyid/table namet_user_addr dataNodedn1 primaryKeyid/!-- 订单模块放在 dn2 --table namet_order dataNodedn2 primaryKeyorder_id/table namet_order_item dataNodedn2 primaryKeyid/!-- 商品模块放在 dn3 --table namet_goods dataNodedn3 primaryKeyid//schema每一张表都完整存在于某个库中Mycat 仅负责将 SQL 路由到对应的数据节点。无 rule因为数据没有被打散。2. 水平分库一张表的数据散列到多个库特点同一张表的结构在多个库中都有数据按分片键分散存储必须配置分片规则rule。与水平分表的核心区别水平分库的 table 里是多个dataNode且没有subTables。为避免和单库分表混淆这里用两张关联表订单表、订单项表同时进行水平分库的示例。schema.xmlschema nameMYCAT_DB checkSQLschemafalse sqlMaxLimit100!-- 两张表都水平分库到 dn1,dn2,dn3共用同一个 rule --table namet_order dataNodedn1,dn2,dn3 rulemod_rule primaryKeyid/table namet_order_item dataNodedn1,dn2,dn3 rulemod_rule primaryKeyid//schemarule.xml取模分片tableRule namemod_rulerulecolumnsid/columns !-- 分片键 --algorithmmod-long/algorithm/rule/tableRulefunction namemod-long classio.mycat.route.function.PartitionByModproperty namecount3/property !-- 分为3个库 --/function说明分片键id写在 rule 的columns里物理表中必须包含该字段。多张表共用mod_ruleMycat 会根据每张表的分片键独立路由到对应库完全不需要重复定义 rule。因为两张表的分片规则一致关联查询如JOIN ON id时数据大概率落在同一分片节点避免跨库 JOIN。3. 垂直分表单库内大表拆小表主表 扩展表特点在同一个数据库中将一张表的字段拆分成多张表如常用字段与大字段分离。核心真相垂直分表是纯人工手动拆表Mycat 不参与任何字段拆分或合并逻辑它只负责声明表在哪个节点场景商品表拆分为t_goods_main高频小字段和t_goods_ext大文本字段。物理建表自己在 MySQL 中执行-- 主表常用字段CREATE TABLE t_goods_main(id INT PRIMARY KEY,goods_name VARCHAR(50),price DECIMAL(10,2),stock INT);-- 扩展表大字段、冷门字段CREATE TABLE t_goods_ext(goods_id INT PRIMARY KEY, -- 与主表 id 一一对应goods_detail LONGTEXT,goods_img TEXT);schema.xml 配置schema nameMYCAT_DB checkSQLschemafalse sqlMaxLimit100!-- 两张表都在同一个数据节点 dn1没有 rule --table namet_goods_main dataNodedn1 primaryKeyid/table namet_goods_ext dataNodedn1 primaryKeygoods_id//schemaMycat 这段配置只做了三件事告诉 Mycat 这两张表都在dn1库中声明各自的主键字段不控制任何字段字段如何拆分完全由建表时决定。正因为是“纯手动”所以垂直分表不需要任何 rule增删改查也需要自己写关联 SQL见下文第 7 节。4. 水平分表单库内逻辑表拆多张物理子表特点在同一个数据库中一张逻辑表对应多张物理子表如t_log_0,t_log_1……数据按分片键自动路由到对应的子表。必须配置 rule。schema.xmlschema nameMYCAT_DB checkSQLschemafalse sqlMaxLimit100!-- 单库 dn1分成 4 张子表t_log_0 ~ t_log_3 --table namet_log subTablest_log_$0-3 dataNodedn1 rulelog_rule primaryKeyid//schemarule.xml单库内取模tableRule namelog_rulerulecolumnsid/columnsalgorithmmod-long/algorithm/rule/tableRulefunction namemod-long classio.mycat.route.function.PartitionByModproperty namecount4/property !-- 单库分4张表 --/function注意subTablest_log_$0-3表示物理表名称为t_log_0、t_log_1、t_log_2、t_log_3Mycat 会根据分片算法自动计算目标子表。5. 组合水平分库 水平分表常用将数据先分到多个库每个库内再分多张子表。例如订单表分 2 个库每个库内分 2 张子表总共 4 个分片。schema.xmltable namet_order dataNodedn1,dn2 subTablest_order_$0-1 ruleorder_rule primaryKeyid/rule.xmlfunction namemod-long classio.mycat.route.function.PartitionByModproperty namecount4/property !-- 2库 × 2表 4 --/function6. 多表分片规则复用与独立性6.1 同分片规则 → 复用同一个 rule推荐如果多张关联表都按照相同的分片键和算法分片只需定义一个 rule多次引用即可。!-- schema.xml --table namet_order dataNodedn1,dn2,dn3 rulemod_rule primaryKeyid/table namet_order_item dataNodedn1,dn2,dn3 rulemod_rule primaryKeyid/rule.xml中只写一份mod_rule全局复用。6.2 不同表分片规则可以不一致允许对于毫无关联的业务表可以使用完全不同的分片键和分片算法。!-- schema.xml --table namet_order dataNodedn1,dn2,dn3 rulemod_rule primaryKeyorder_id/table namet_pay dataNodedn1,dn2,dn3 rulerange_rule primaryKeyuser_id/rule.xml定义两套独立的规则!-- 规则1取模 --tableRule namemod_rulerulecolumnsorder_id/columnsalgorithmmod-long/algorithm/rule/tableRule!-- 规则2范围分片 --tableRule namerange_rulerulecolumnsuser_id/columnsalgorithmrange-hash/algorithm/rule/tableRulefunction namemod-long classio.mycat.route.function.PartitionByModproperty namecount3/property/functionfunction namerange-hash classio.mycat.route.function.AutoPartitionByLongproperty namemapFilepartition-hash-long.txt/property/function6.3 重要原则同业务关联表必须统一分片字段订单、订单项、物流、支付等需要关联查询的表必须使用相同的分片键和分片规则否则 JOIN 将跨库性能极差甚至报错。毫无关联的独立表如用户表按 uid 分日志表按 id 分允许不同。正确示例订单表和订单详情表都按user_id分片且共用user_rule联表时数据在同一个库性能高。!-- 两张表都使用同一个 user_rule分片键都是 user_id --table namet_order dataNodedn1,dn2 ruleuser_rule primaryKeyid/table namet_order_item dataNodedn1,dn2 ruleuser_rule primaryKeyid/同时物理表中必须都包含user_id字段否则 Mycat 无法正确路由。CREATE TABLE t_order (id INT, user_id INT, ...);CREATE TABLE t_order_item (id INT, user_id INT, order_id INT, ...);7. 垂直分表的插入与查询注意事项垂直分表后插入数据必须使用两条 INSERT 语句不能一条 SQL 同时插入两张表。START TRANSACTION;INSERT INTO t_goods_main(id, goods_name, price) VALUES(1001, 手机, 2999);INSERT INTO t_goods_ext(goods_id, goods_detail) VALUES(1001, 超长详情...);COMMIT;查询时只需要一条联表 SQL因为两表在同一库性能很好SELECT m.*, e.goods_detailFROM t_goods_main mLEFT JOIN t_goods_ext e ON m.id e.goods_idWHERE m.id 1001;Mycat 在此处只负责将 SQL 路由到正确节点不做任何自动拆分或合并字段的操作。8. 四种策略本质对比总结策略核心操作是否拆分数据是否需要 rule分片键位置Mycat 参与度垂直分库不同表存不同库否不需要无按配置路由表到指定节点水平分库同一张表数据散列到多个库是必须rule 的 columns自动分片路由垂直分表同库内一张表拆成多张表字段拆分否不需要无只登记表位置拆分人为完成水平分表同库内逻辑表拆成多张物理子表是必须rule 的 columns自动路由到正确的子表