缺点在于:数据分散不均匀,某些表的数据量特别大,某些表的数据量很小。因为某些用户下单量多,打个比方,1000-2000这个范围内的用户,下单特别多,
而他们的id根据计算规则,都是分到了x库x表。造成这个表的数据量大,单表的数据量撑到极限后,咋办呢?
总结一下:每种分库分表方案也不是十全十美,都是有利有弊的。目前来说,这种使用用户id来切分订单数据的方案,还是被大部分公司给使用。实际效果还不错。程序员省事,至于数据量暴涨,以后再说呢。毕竟公司业务发展到什么程度,不知道的,项目存活期多久,未来不确定。先扛住再说。
比较好的方案是不是:又能均匀分散、又能避免单表数据量暴涨方便扩容。以前看过一篇文章介绍过使用节点来存储分库分表。笔者暂时没完整的思路。
二、查询需求的考虑
方案一的查询问题
方案一的情况下,由于是按照订单号做分散数据到多个库、多个表。如果需要查询a用户的所有订单,咋办?需要跨库、跨表查询。
这样效率低。不可行。
方案二的查询问题
如果是按照uid来切分订单数据,在实际应用中一些很频繁的查询需求像下面这样:
1、后台、前台,往往是输入一个订单号,查询这个订单的数据。select操作
2、然后修改这个订单的相关状态。update操作。
由于是,按照用户编号将订单数据分散在各个库、各个表中。
那输入订单号,怎么知道去哪个库、哪个表查询呢?不可能所有的库、所有表都查询一遍,效率太低,不可行。
三、解决办法:建立用户id和订单号的索引关系表
无论是根据用户id来切分订单,还是根据订单号切分数据。总不能十全十美的。
写到这里,发现真的没有一种技术方案是十全十美的,看,使用用户id来切分订单,好处是有了,坏处也出来了。
不过没关系,早要有心里承受:不要觉得技术是完美无缺的。针对这种情况,想办法去解决办法。
思路:既然是根据订单号分散订单数据,如果需要知道某个用户所有的订单。只要我能知道了a用户的所有的订单号,那么就可以根据订单号定位到表名称了。
思路:既然是根据用户id来分散订单数据的。那么只要知道了这个订单号是谁的(得到了用户id),就能知道去哪个库、哪个表查询数据了。
那怎么知道是谁的呢?建立一个索引关系表,暂且叫做订单用户关系索引表order_user_idx。咱们命名为了保持维护性,还是一看能够知道是干嘛用的。
存储的数据包括两项:订单号、用户编号。
这样输入订单号,可以去查询索引关系表,获取到用户编号。
得到了用户编号,问题解决了。订单信息是根据用户编号分库分表的,可以直接定位到x库x表了。
当创建订单的时候,就要把关系插入到表里面去了。保存关系记录时,为了减低用户等待时间,不需要实时,做成异步。加入到消息队列中去操作。
订单用户索引关系表的性能优化
考虑到,一个用户的下的订单可能是几十个,也可能是几百个,随着时间的推移,会越来越多。这个索引关系表,也不能使用单表存储。
所以对这个订单用户关系索引表,也要进行分库分表:直接根据订单号取模进行分库分表。是不是感觉挺麻烦了。确实麻烦。不过能解决问题就好。暂时没想到其他办法了。
一个订单,在创建的时候,就已经分配好给指定用户了。只是一个关系对应,以后也不会变化。
根据这个特点。订单用户索引关系表,其实可以放到内存中缓存起来应对查询需求(数据库那张索引关系表也要有,数据要持久化)。
平时查询的时候,走内存缓存查询。如果查询不到,再走数据库查询一下关系。这样速度就很快了。
结语:水平分表,其实折腾起来工作量挺大的,切分了后,出现新的问题,代码查询又得改,要提供其他解决办法。所以经常看到别人说,能不水平分表,尽量不要分,业务没达到瓶颈,先用硬件扛住,后面再考虑水平切分数据。看银行、联通这些有钱的企业,使用性能强劲的oracle搭配小型机服务器,单表的数据量达到十多亿。小型机是专门定制的,几十万一台。性能很强。分库分表是很耗费时间、当你交易量做到上亿规模的时候,那时,公司的实力应该可以了,经济方面有足够的实力聘请经验丰富的技术来重构。
思考一、b2b平台的订单分卖家和买家的时候,选择什么字段来分库分表呢?
上面讨论的情况是,b2c平台。订单的卖家就一个,就是平台自己。
b2b平台,上面支持开店,买家和卖家都要能够登陆看到自己的订单。
先来看看,分表使用买家id分库分表和根据卖家id分库分表,两种办法出现的问题