先切业务,再切数据
确定动刀后,很多团队想象中的第一步就是「订单表按 user_id 切成 64 份」——先别急。在水平切之前,还有一次更便宜、更安全的手术:垂直拆分。它的刀口不在「同一业务的行」上,而在「不同业务之间」和「同一行的字段之间」。一句话概括:按业务切库,按冷热切字段。
垂直分库:给业务划地盘
单体时代的库往往是个大杂烩:订单、商品、用户、营销、日志全挤在一个 MySQL 里。垂直分库按业务边界把这些表分到不同的库(实例)上:订单库、商品库、用户库各管各的。收益有三层:容量与负载隔离——订单库写得多,营销库读得多,各自扩各自的,互不抢资源;故障隔离——营销库挂了,订单查询安然无恙;演进铺垫——业务边界清晰后,服务化改造(从单体到微服务的演进)有了数据层的对位。
代价也要认清:跨库 JOIN 从此消失,原来一条 SQL 关联订单和商品的查询,要么冗余数据、要么应用层聚合、要么上跨库方案;跨库事务登场——订单和库存原来在一个事务里,现在隔着两个库。这就是为什么垂直分库往往和微服务化一起做——数据边界和服务边界是同一个问题。
垂直分表:给主表瘦身
库内还有一层更细的刀:把一张宽表按字段冷热拆成两到三张。商品表是典型:高频访问的是标题、价格、状态这些核心字段,详情页的富文本描述动辄几十 KB,却只在详情页被读一次。把它拆出去单独存放,主表的每一行都轻了一截——行越短,一页放得下的行越多,Buffer Pool 装得下的热数据越多,命中率越高。常见刀法有三类:
冷热拆: item(核心字段) + item_ext(详情富文本,低频)
长度拆: user(高频短字段) + user_profile(简介/设置,中频)
访问拆: order(交易字段) + order_stat(统计字段,后台用)拆分的判断标准就一条:访问频率和长度是否与主字段群明显脱节。脱节的拆出去,同频的留着——拆得太碎,读一次数据要 join 两张表或查两次,得不偿失。
垂直拆的天花板
垂直拆分便宜、安全、边界清晰,但它有一个改不掉的天花板:它切的是维度,不是行数。订单库独立出来了,订单表还是两亿行;详情字段请出去了,核心字段的行数一点没少。单业务的行数规模和写 QPS,垂直拆无能为力——那是水平拆的战场。所以标准的动刀顺序是:先垂直理顺业务边界,再水平解决行数与写瓶颈。顺序反了,等于在烂地基上砌墙。
业务边界理顺了,真正的硬仗开始:同一张订单表的两亿行,怎么切才对?Range、Hash、查表三种刀法各有利弊,下一篇逐一开刃。
评论 (0)