V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
putyy
V2EX  ›  问与答

mysql 分表的一些方案

  •  
  •   putyy · 2020-07-31 11:24:02 +08:00 · 1212 次点击
    这是一个创建于 1567 天前的主题,其中的信息可能已经有所发展或是发生改变。

    写在前面

    1. 为什么要分表呢?这个看似不是问题的问题先埋个点

    进入主题吧

    **ps: 这里只分享一下业务上面进行分表的一些方法吧

    1. 垂直分表

    垂直分表在业务开发过程中应该是随处可见的,比如:用户相关的表

    CREATE TABLE `user` (
      `uid` int(11) unsigned NOT NULL AUTO_INCREMENT,
      `user_name` varchar(50) DEFAULT '' COMMENT '用户登录名',
      `password` char(32) DEFAULT '' COMMENT '用户登录密码',
      `is_del` tinyint(1) unsigned DEFAULT '1' COMMENT '1,正常 2,删除',
      `create_time` char(10) DEFAULT '0' COMMENT '录入时间',
      `update_time` char(10) DEFAULT '0' COMMENT '更新时间',
      PRIMARY KEY (`uid`)
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='用户基本表';
    
    CREATE TABLE `user_info` (
      `uid` int(11) unsigned NOT NULL,
      `head_img` varchar(50) DEFAULT '' COMMENT '头像',
      `nick_name` varchar(50) DEFAULT '' COMMENT '昵称',
      `sign_content` varchar(255) DEFAULT '' COMMENT '个性签名',
      `update_time` char(10) DEFAULT '0' COMMENT '更新时间',
      PRIMARY KEY (`uid`)
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='用户信息表';
    
    ......
    

    如上所见,垂直分表就是把一个实体按照某种属性进行分类划分成多个表。


    .

    2.水平分表
    1. 范围取表方式

    比如用户联系信息: 我们可以按照范围分表

    1-100w: user_info_1 100w-200w: user_info_2

    CREATE TABLE `user_info_{{1+}}` (
      `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
      `uid` int(11) NOT NULL DEFAULT '0' COMMENT '用户 uid',
      `mobile` varchar(20) NOT NULL DEFAULT '' COMMENT '手机号',
      `address` varchar(50) NOT NULL DEFAULT '' COMMENT '住址',
      ......
      `is_del` tinyint(1) unsigned DEFAULT '1' COMMENT '1,正常 2,删除',
      `create_time` char(10) DEFAULT '0' COMMENT '录入时间',
      `update_time` char(10) DEFAULT '0' COMMENT '更新时间',
      PRIMARY KEY (`id`),
      UNIQUE KEY `uid_index` (`uid`) USING BTREE
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='用户联系信息表';
    

    .

    2. 过某种特定的算法分表(取模、哈希)

    取模:比如用户 ID%100,分 100 张表

    CREATE TABLE `visit_record_{{1-100}}` (
      `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
      `uid` int(11) NOT NULL DEFAULT '0' COMMENT '所属人 uid',
      `source_id` int(11) NOT NULL DEFAULT '0' COMMENT '资源 id',
      `type_mark` int(10) NOT NULL DEFAULT '0' COMMENT '资源类型',
      ......
      `create_time` char(10) DEFAULT '0' COMMENT '录入时间',
      `update_time` char(10) DEFAULT '0' COMMENT '更新时间',
      PRIMARY KEY (`id`),
     UNIQUE KEY `st_index` (`source_id`,`type_mark`) USING BTREE
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='用户资源访问记录';
    

    优缺点:

    取模方式:

    冷热数据比较均衡,但扩展性比较差,一但数据量超过预期,原定表数量就无法承载,再加表就比较麻烦

    范围方式:

    扩展性比较强,但是一般新用户是比较活跃的,大部分都查询到新表上面,就导致冷热数据不均衡要解决这样的问题可以两者结合互补, 首先根据范围进行分组: 比如用户 1~1000w,分为 10 张表,然后 uid%10 得到具体表、相当于 1-10 表的总数据量已经确定了,先取范围再取模,扩展性问题就不存在了

    原文

    http://www.putyy.com/article/53

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1018 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 21:47 · PVG 05:47 · LAX 13:47 · JFK 16:47
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.