当前位置: 移动技术网 > IT编程>数据库>Mysql > MySQL分库分表与水平分割取模案例

MySQL分库分表与水平分割取模案例

2018年02月08日  | 移动技术网IT编程  | 我要评论
分表分库 当项目比较大的时候,基本上都会进行分表分库的 后面就讲讲什么时候需要分库,什么时候需要分表 什么时候需要分库 垂直分割 垂直拆分就是要把表按模块划分到不同数据库

分表分库

当项目比较大的时候,基本上都会进行分表分库的

后面就讲讲什么时候需要分库,什么时候需要分表

什么时候需要分库

垂直分割

垂直拆分就是要把表按模块划分到不同数据库表中(当然原则还是不破坏第三范式),这种拆分在大型网站的演变过程中是很常见的。当一个网站还在很小的时候,只有小量的人来开发和维护,各模块和表都在一起,当网站不断丰富和壮大的时候,也会变成多个子系统来支撑,这时就有按模块和功能把表划分出来的需求。其实,相对于垂直切分更进一步的是服务化改造,说得简单就是要把原来强耦合的系统拆分成多个弱耦合的服务,通过服务间的调用来满足业务需求看,因此表拆出来后要通过服务的形式暴露出去,而不是直接调用不同模块的表,淘宝在架构不断演变过程,最重要的一环就是服务化改造,把用户、交易、店铺、宝贝这些核心的概念抽取成独立的服务,也非常有利于进行局部的优化和治理,保障核心模块的稳定性

垂直拆分用于分布式场景。

当大团队在做电商项目的时候,基本上都会将一个项目进行拆分,拆分成n个小项目

这样做的好处就是,基于逆向服务架构,会拆分多个小项目,每个小项目都有自己单独的数据库,这样的话小项目之间互不影响。

这样叫做垂直分割。

比如:

会员数据库、订单数据库、支付数据库等等这样来分

可以减低开发团队之间的耦合度。就比如,某个团队把一个数据库弄挂了,对另外的团队基本没有影响。假如全部用的一个数据库,是不是全部都挂了,所有用到那个数据库的团队项目进度都要延期

什么时候需要分表

水平分割

上面谈到垂直切分只是把表按模块划分到不同数据库,但没有解决单表大数据量的问题,而水平切分就是要把一个表按照某种规则把数据划分到不同表或数据库里。例如像计费系统,通过按时间来划分表就比较合适,因为系统都是处理某一时间段的数据。而像SaaS应用,通过按用户维度来划分数据比较合适,因为用户与用户之间的隔离的,一般不存在处理多个用户数据的情况,简单的按user_id范围来水平切分

为什么需要分表,就比如,一个表,几十年的数据全部在那个表中,查找,无论你加索引还是怎么,查询都需要很长的时间。
这个时候就需要做一个分表、分表的规则,一般按照业务需求来定。没有统一的分法。

比如:

我们的业务场景,主要是存放日志的,日志是需要按照每年存放的

这个时候分表的话,就根据年份来分

再如腾讯的QQ号,根据什么来分表

如果是根据位数,最大的缺点是分部不均匀!

另外如会员系统,通过手机号登录。会员表中

可以通过手机号前三位分表(有一些项目是这样做的,没多大问题),比如136 138 155等,但是都不是怎么均匀

最好通过水平分割(取模算法)来分割

假如我们需要把一个表分成3个表,我们可以把一个是数字的字段,比如int主键(userid)。

这个时候,我们可以对表中数据的userid字段对3进行取模,然后对于不同的余数进行分表

这里的取模字段不能用自动增长的

实现取模算法,我们需要有专门的一张表存放对应的userid字段(用来取模的字段)。

在插入行时,先生成id,然后在该表中取出对应的userid,然后赋值过去

是否需要分表,这个依据项目经验和实际业务情况来的。一般MySQL单表1000W左右的数据是没有问题的(前提是应用系统和数据库等层面设计和优化的比较好)

当然,如果需要分表,肯定是需要提前计划半年或者一年计划的。

通俗理解垂直分割和水平分割:水平拆分行,行数据拆分到不同表中, 垂直拆分列,表数据拆分到不同表中

水平分割取模算法案例

使用取模算法分表的最大好处就是,可以非常均匀的分配

首先创建三张表 user0 / user1 /user2 , 然后我再创建 uuid表,该表的作用就是提供自增的id。

创建数据库: split_horizon

create table user0(
    id int unsigned primary key ,
    name varchar(32) not null default '',
    pwd  varchar(32) not null default ''
)engine=myisam charset utf8;

create table user1(
    id int unsigned primary key ,
    name varchar(32) not null default '',
    pwd  varchar(32) not null default ''
)engine=myisam charset utf8;

create table user2(
    id int unsigned primary key ,
    name varchar(32) not null default '',
    pwd  varchar(32) not null default ''
)engine=myisam charset utf8;


create table uuid(
    id int unsigned primary key auto_increment
)engine=myisam charset utf8;

功能就是 注册分表,以及进行分表查询

项目很简单,看下了解下分表是怎么回事就好,

Service代码

package com.uifuture.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

/**
 * Created with IntelliJ IDEA.
 * User: 陈浩翔.
 * Date: 2018/2/5.
 * Time: 下午 10:28.
 * Explain:
 */
@Service
public class UserService {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * 注册的代码
     * @param name
     * @param pwd
     * @return
     */
    public String regit(String name,String pwd){
        //1.生成userid ,-  先获取到 自定增长ID
        String insertUUidSql = "insert into uuid values(null)";//插入空数据,这里的id是自动增长的
        jdbcTemplate.update(insertUUidSql);//执行
        Long userid = jdbcTemplate.queryForObject("select last_insert_id()", Long.class);//查询到最近的添加的主键id
        //2.存放具体的那张表中 - 也就是判断存储表名称
        String tableName = "user" + userid % 3;
        //3.插入到具体的表中去- 注册数据
        String insertUserSql = "INSERT INTO " + tableName + " VALUES ('" + userid + "','" + name + "','" + pwd + "');";
        System.out.println("insertUserSql:" + insertUserSql);
        jdbcTemplate.update(insertUserSql);
        return "success";
    }

    /**
     * 通过userid查询name
     * @param userid
     * @return
     */
    public String get(Long userid) {
        //具体哪张表
        String tableName = "user" + userid % 3;
        String sql = "select name from " + tableName + " where id="+userid;
        System.out.println("SQL:" + sql);
        return jdbcTemplate.queryForObject(sql, String.class);//执行查询出name
    }


}

Controller代码

package com.uifuture.controller;

import com.uifuture.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Created with IntelliJ IDEA.
 * User: 陈浩翔.
 * Date: 2018/2/5.
 * Time: 下午 10:44.
 * Explain:
 */
@RestController
public class UserController {
    @Autowired
    private UserService userService;

    /**
     * 演示注册的入口
     * @param name
     * @param pwd
     * @return
     */
    @RequestMapping("/regit")
    public String regit(String name, String pwd) {
        return userService.regit(name, pwd);
    }

    /**
     * 演示获取name
     * @param id
     * @return
     */
    @RequestMapping("/get")
    public String get(Long id) {
        return userService.get(id);
    }

}

分表之后也有些缺点。

1.分页查询

2.查询非常受限制

比如我不查询那个分表的关键字段

所以一般会有主表和次表

主表存放所有的数据。次表根据具体业务需求进行分表

还有mycar中间件具有分表功能,可以学学

取模算法的缺点,如果我们的表发生改变,需要我们重新分,很麻烦

(哈哈,可以使用阿里云的rds云数据库,这样就不用我们关心读写分离,分表分库等等。rds是二次开发的数据库,所以在性能上来说,比其他的关系型数据库是快很多的。可以自己去了解下)

如您对本文有疑问或者有任何想说的,请 点击进行留言回复,万千网友为您解惑!

相关文章:

  • Ubuntu上Vim安装NERDTree插件的详细操作步骤

    Ubuntu上Vim安装NERDTree插件的详细操作步骤

    nerdtree是vim的文件系统浏览器,使用此插件,用户可以直观地浏览复杂的目录层次结构,快速打开文件以进行读取或编辑,以及执行基本的文件系统操作。nerdt... [阅读全文]
  • MySQL 4种常用的主从复制架构

    MySQL 4种常用的主从复制架构

    一主多从复制架构在主库读取请求压力非常大的场景下,可以通过配置一主多从复制架构实现读写分离,把大量的对实时性要求不是特别高的读请求通过负载均衡分部到多个从库上(... [阅读全文]
  • 浅析MySQL 备份与恢复

    1、简介数据无价,mysql作为一个数据库系统,其备份自然也是非常重要且有必要去做。备份的理由千千万,预防故障,安全需求,回滚,审计,删了又改的需求等等,备份的... [阅读全文]
  • 保障MySQL数据安全的一些建议

    数据是企业核心资产,数据对企业而言是最重要的工作之一。稍有不慎,极有可能发生数据无意泄露,甚至被黑客恶意窃取的风险。每年业界都会传出几起大事件,某知名或不知名的... [阅读全文]
  • MySQL如何快速修改表的表结构

    快速修改mysql某张表的表结构--摘录自《mysql管理之道》alter table 表名 modify 列名 数据类型; 这个命令可以修改表结构此外,也可以... [阅读全文]
  • MySQL 行锁和表锁的含义及区别详解

    一、前言对于行锁和表锁的含义区别,在面试中应该是高频出现的,我们应该对mysql中的锁有一个系统的认识,更详细的需要自行查阅资料,本篇为概括性的总结回答。mys... [阅读全文]
  • MySQL 如何查询当前最新事务ID

    写在前面:在个别时候可能需要查看当前最新的事务 id,以便做一些业务逻辑上的判断(例如利用事务 id 变化以及前后时差,统计每次事务的响应时长等用途)。通常地,... [阅读全文]
  • 如何优雅、安全的关闭MySQL进程

    前言本文分析了 mysqld 进程关闭的过程,以及如何安全、缓和地关闭 mysql 实例,对这个过程不甚清楚的同学可以参考下。关闭过程1、发起 shutdown... [阅读全文]
  • 详解MySQL8.0​ 字典表增强

    详解MySQL8.0​ 字典表增强

    mysql中数据字典是数据库重要的组成部分之一,information_schema首次引入于mysql 5.0,作为一种从正在运行的mysql服务器检索元数据... [阅读全文]
  • 简述MySQL InnoDB存储引擎

    前言:存储引擎是数据库的核心,对于 mysql 来说,存储引擎是以插件的形式运行的。虽然 mysql 支持种类繁多的存储引擎,但最常用的当属 innodb 了,... [阅读全文]
验证码:
移动技术网