海量跨境商品数据库分表分库优化方案
为什么需要分表分库
当跨境商品数量达到千万甚至亿级时,单表查询会变得极其缓慢。
例如 SELECT * FROM products WHERE seller_id = 123 可能需要数秒。
分表分库可以将数据分散到多个物理库表,显著降低单表压力,提升并发处理能力。
分片策略选择
对于跨境商品数据,最常见的分片键是 seller_id(卖家ID)或 product_id(商品ID)。
按卖家分片能避免热点数据集中在单个分片,同时便于按卖家维度管理。
如果查询条件经常涉及商品ID,也可以使用哈希分片。
建议以 seller_id 作为主分片键,并辅以 product_id 作为子分片键。
操作步骤:以ShardingSphere-JDBC为例
第1步:准备环境
- 两台MySQL 8.0实例(可分别称为
db0和db1) - 添加ShardingSphere-JDBC依赖(Maven或Gradle引入)
第2步:配置分片规则
在你的应用配置文件中写入如下内容:
# sharding-jdbc.yml
databaseName: cross_border_db
shardingRule:
tables:
products:
actualDataNodes: db0.products_${0..1}, db1.products_${0..1}
tableStrategy:
inline:
shardingColumn: seller_id
algorithmExpression: products_${seller_id % 2}
databaseStrategy:
inline:
shardingColumn: seller_id
algorithmExpression: db${seller_id % 2}
这段配置表示:根据seller_id对2个库和2个表进行水平拆分,共4个分片。
第3步:创建分片表
在db0和db1中分别执行:
CREATE TABLE products_0 (
id BIGINT PRIMARY KEY,
seller_id BIGINT NOT NULL,
product_name VARCHAR(255),
price DECIMAL(10,2),
INDEX idx_seller (seller_id)
) ENGINE=InnoDB;
CREATE TABLE products_1 (
id BIGINT PRIMARY KEY,
seller_id BIGINT NOT NULL,
product_name VARCHAR(255),
price DECIMAL(10,2),
INDEX idx_seller (seller_id)
) ENGINE=InnoDB;
第4步:验证插入与查询
插入一条记录:
INSERT INTO products (id, seller_id, product_name, price) VALUES (1, 1001, '商品A', 29.99);
ShardingSphere会根据seller_id % 2自动路由到相应库表。
使用EXPLAIN查看路由结果:
EXPLAIN SELECT * FROM products WHERE seller_id = 1001;
避坑指南
- 跨分片查询:不要用
JOIN关联不同分片的表,尽量按分片键过滤。 - 数据倾斜:如果某个卖家数据量极大,可改用哈希或范围分片。
- 分布式事务:简单场景可用
XA,生产环境推荐Seata或TCC模式。 - 数据迁移:先停止写操作,导出单表数据,按分片规则导入新表。
常见问题
Q:分片键选择错误怎么办?
A:必须根据最频繁的查询条件确定分片键,否则会产生全路由查询,性能反而下降。
Q:能否动态扩容分片?
A:可以,但需要停机维护或使用一致性哈希进行在线迁移。
效果验证
插入100万条商品数据(按seller_id均匀分布),对比分片前后单次查询耗时:
- 单库单表:平均150ms
- 分4个分片后:平均18ms
使用SHOW STATUS LIKE 'Qps';监控系统查询吞吐量,可看到明显提升。
如果你的跨境商品数据量还在增长,建议尽早规划分表分库方案,按本文步骤执行后可根据实际情况调整分片数量。