SupCube

  • 主页
  • 随笔
所有文章 友链 关于我

SupCube

  • 主页
  • 随笔

大数据存储之水平分表方案

2021-05-10 阅读量4395

      随着互联网的发展潮流,慢慢衍射出需要大数据存储的场景;而且在各行各业中大数据存储场景越来越常见;在面对大数据的读取过程中我们往往会考虑到ES、Redis等非关系型数据库的使用;这些技术的引入的确解决了数据读取问题,然而这些数据也需要在关系型数据库中存储,那么如何有效解决这一问题呢?本文拿mysql为例来阐述对于大数据存储方面的一些方案;

     一,分表场景    

    对于Mysql而言在面对大数据存储的场景中若数据量超过一定量(一般参考500W)之后就要考虑分库或者分表方式来建立关系型数据库;(如果数据量特别大,可以考虑分库方案,本文只考虑分表方案);

    二,分表类型

    Mysql常用分表策略有:垂直拆分(纵向拆分)和水平拆分(横向拆分)

    所谓垂直拆分就是将一个大表拆分成:1:1 的一些小表;它们的拆分原则往往是依据业务不同,即“一失一的”,这样分的目的是减少单个表的存储空间;表与表之间通过业务外键关联;这样拆分不会减少单表的数据量但是可以提升对标的操作性能;

    所谓水平拆分是将一个大表拆分成一系列小表;这些表之间是完全并列的关系;各个表之间的结构完全一致;(本文主要讨论水平分表方案)

   三,水平分表的方法

   水平分表有些数据库中间件可以很方便实现此功能如mycat;但是通过mycat官方指出采用mycat方式来进行分表,因为内部可能考虑复杂情形的联合查询等情况因此性能会降低10%-30%对于性能不是很强劲的mysql来说这些损失也是挺可惜的;因此业界普遍采用路由表方式来进行“手动”维护分表;目前分表一般采用如下几种:1)Hash、取模;2)时间;3)区间;4)路由表;

  1.    所谓的分表方式均只有一个目标即如何确认数据的存放位置。即通过如上算法确定表序号;

   3.1Hash、取模
   该方法是对操作的数据主键进行hash取模追踪取到对应的表序号;
   该算法的核心是找到表的下标,若id为字符串则可以对id进行hash最终取模得到一个下标;如对一个新闻表采用分表方式存储,若拆分为10个表,若需要插入id为20001的数据则该条数据需要存到下标为1的表中(news_1);
   按照id对该表进行读取同样需要计算该id所对应的数据存在于哪个表中;
   3.2时间
   该方法对于日志数据较为普遍,譬如对于大量日志数据的存储则可以按照时间格式命名表的后缀;如同样对于新闻表采用按照时间方式分表(如一个月一张表)可以采用new_202105的方式进行。如果我们需要存储创建时间在2021年五月的数据则存放在后缀为202105的表中;
   读取同样需要指明当前数据存放在哪个时间段内;
   3.3区间
   该方法可以将各个表内的数据均匀分配;譬如规定好每个表中的数据10000000(1KW)则可以根据id计算出当前数据所在的数据表;如id范围为:【1——10000000】存在于new_1中;【10000001-20000000】存在于new_2中。这样分表的优点在于容易计算表的后缀:(id/10000000+1)但是若对于id不为数字类型则实现起来有困难;
   3.4路由表
   该方法是最灵活的实现方式;对于各个分表内部存放的数据范围有明确的标识,我们需要新建一个路由表来存放如上数据;

+-----------------+-------------+------+-----+---------+----------------+
| Field           | Type        | Null | Key | Default | Extra          |
+-----------------+-------------+------+-----+---------+----------------+
| id              | int(11)     | NO   | PRI | NULL    | auto_increment |
| root_table_name | varchar(64) | NO   |     | NULL    |                |
| table_name      | varchar(64) | NO   |     | NULL    |                |
| min_id          | int(11)     | NO   |     | NULL    |                |
| max_id          | int(11)     | NO   |     | NULL    |                |
+-----------------+-------------+------+-----+---------+----------------+


对于操作一条数据可以通过该表查询本数据所在的分表名称;
这样做的优点很明显:
1)可以灵活控制每个分表的数据量;
2)扩展表或者调整每个分表的数据很方便;

+----+-----------------+------------+----------+----------+
| id | root_table_name | table_name | min_id   | max_id   |
+----+-----------------+------------+----------+----------+
|  2 | document        | document_1 | 12000001 | 35000000 |
+----+-----------------+------------+----------+----------+

如定义id范围在:【12000001-35000000】之间的数据存在于document_1中;

    


赏

谢谢你请我吃糖果

支付宝
微信

扫一扫,分享到微信

微信分享二维码
Mysql-常用命令
京公网安备11011102002544 © 京ICP备2024068849号-1
智汇魔方:http://www.supcube.com
  • 所有文章
  • 友链
  • 关于我
  • 切水果
  • json格式化
  • 自动分组
  • 集合差集