Skip to content

Latest commit

 

History

History
43 lines (29 loc) · 2.59 KB

File metadata and controls

43 lines (29 loc) · 2.59 KB

关于分库分表思路的工作总结(1)

最近工作上在做基础服务的性能优化,分库分表自然是大数据表常用优化利器之一,除此之外还有针对查多增少的场景进行缓存优化也是常见方法,下面 主要总结下分库分表时候不同业务表的一些处理思路。 注意,文中分库分表分表 并不做特别区分,两者在本文讨论场景下的处理思路都是一样的。


主键是个字符串

除非公司初期的工程师经验丰富(这很难),对于大多数不断壮大的公司来说,工程师一波一波的更替,总会遇到一些高速堆需求时候,前同事们一时不小心 考虑不周,遗留下的技术债。 尤其是表结构,一旦最初设计不合理,后面很难改正过来,比代码层面换编程语言还难。相反每次建表时候,多迟疑下,更合理些,后面开发会顺利很多。

token user_id x y z
asc893ffdads 6210983232 字段x 字段y 字段z

假如入有上面一个表,其中token 是个字符串且是这个表的主键。 现在需要对这个表进行水平分表,同时不影响现有对外暴露的接口业务:

  • 根据token查询,getByToken()
  • 根据user_id查询,getByUserId()

经过调研发现80%请求都是byToken.所以 对token取hash值 ,然后取模。这时候getByToken可以直接定位到对应的分表,进行查询。 而对于user_id,由于其可能散落在任何一个分表中,那么就需要并行把所有分表都查一次,然后聚合。 如果一个user_id只对应一个token,岂不是n-1次查询都是无效的(n是分表数量),本来需要查一次的,分完后居然多查了很多次,而且 大多是无效的消耗,虽然其只占了20%的流量。

还想优化怎么办? 再次回归到业务,分析发现业务getByUserId接口都是查询user_id>0 的,而此类数据3~5年内也就千万级别,所以再次优化如下: 建立一个映射表userid_token_map,表中只存有user_id--->token 两个字段的映射关系,其他业务字段不要。然后当getByUserId时候,先从映射表查询到对应的token, 然后再通过token直接定位到对应表,获取其他业务字段。这时候就上面n从请求降低为2次了。可以接受。

还有一些思考:

  • 覆盖索引在映射表中那些业务下可以应用。
  • 怎么判断衡量添加map映射方式是一种治标不治本处理方式 or 完善解决
  • 万一若干年后map映射表需要分表,是否可行。
  • 根本上如何解决,最初表该怎样设计。