【MySQL性能优化】MySQL分库分表与水平分割取模案例(三)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 【MySQL性能优化】MySQL分库分表与水平分割取模案例(三)

欢迎访问原文:

【MySQL性能优化】MySQL分库分表与水平分割取模案例(三)

分表分库


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

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


什么时候需要分库


垂直分割


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

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

当大团队在做电商项目的时候,基本上都会将一个项目进行拆分,拆分成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);
    }
}

其他的代码就见github的项目啦

项目地址:

GITHUB源码地址: 点我进行访问

分表之后也有些缺点。

1.分页查询

2.查询非常受限制

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


所以一般会有主表和次表

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

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


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

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


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
2月前
|
存储 算法 关系型数据库
(二十二)全解MySQL之分库分表后带来的“副作用”一站式解决方案!
上篇《分库分表的正确姿势》中已经将分库分表的方法论全面阐述清楚了,总体看下来用一个字形容,那就是爽!尤其是分库分表技术能够让数据存储层真正成为三高架构,但前面爽是爽了,接着一起来看看分库分表后产生一系列的后患问题,注意我这里的用词,是一系列而不是几个,也就是分库分表虽然好,但你要解决的问题是海量的。
173 3
|
19天前
|
存储 SQL 关系型数据库
【MySQL调优】如何进行MySQL调优?从参数、数据建模、索引、SQL语句等方向,三万字详细解读MySQL的性能优化方案(2024版)
MySQL调优主要分为三个步骤:监控报警、排查慢SQL、MySQL调优。 排查慢SQL:开启慢查询日志 、找出最慢的几条SQL、分析查询计划 。 MySQL调优: 基础优化:缓存优化、硬件优化、参数优化、定期清理垃圾、使用合适的存储引擎、读写分离、分库分表; 表设计优化:数据类型优化、冷热数据分表等。 索引优化:考虑索引失效的11个场景、遵循索引设计原则、连接查询优化、排序优化、深分页查询优化、覆盖索引、索引下推、用普通索引等。 SQL优化。
165 15
【MySQL调优】如何进行MySQL调优?从参数、数据建模、索引、SQL语句等方向,三万字详细解读MySQL的性能优化方案(2024版)
|
19天前
|
存储 SQL 关系型数据库
一篇文章搞懂MySQL的分库分表,从拆分场景、目标评估、拆分方案、不停机迁移、一致性补偿等方面详细阐述MySQL数据库的分库分表方案
MySQL如何进行分库分表、数据迁移?从相关概念、使用场景、拆分方式、分表字段选择、数据一致性校验等角度阐述MySQL数据库的分库分表方案。
一篇文章搞懂MySQL的分库分表,从拆分场景、目标评估、拆分方案、不停机迁移、一致性补偿等方面详细阐述MySQL数据库的分库分表方案
|
9天前
|
存储 关系型数据库 MySQL
mysql-性能优化(一)
mysql-性能优化(一)
|
1月前
|
监控 关系型数据库 MySQL
zabbix agent集成percona监控MySQL的插件实战案例
这篇文章是关于如何使用Percona监控插件集成Zabbix agent来监控MySQL的实战案例。
31 2
zabbix agent集成percona监控MySQL的插件实战案例
|
17天前
|
关系型数据库 MySQL 数据处理
针对MySQL亿级数据的高效插入策略与性能优化技巧
在处理MySQL亿级数据的高效插入和性能优化时,以上提到的策略和技巧可以显著提升数据处理速度,减少系统负担,并保持数据的稳定性和一致性。正确实施这些策略需要深入理解MySQL的工作原理和业务需求,以便做出最适合的配置调整。
69 6
|
3天前
|
SQL 存储 关系型数据库
深入 MySQL 的执行计划与性能优化
深入 MySQL 的执行计划与性能优化
11 0
|
2月前
|
存储 关系型数据库 MySQL
MySQL bit类型增加索引后查询结果不正确案例浅析
【8月更文挑战第17天】在MySQL中,`BIT`类型字段在添加索引后可能出现查询结果异常。表现为查询结果与预期不符,如返回错误记录或遗漏部分数据。原因包括索引使用不当、数据存储及比较问题,以及索引创建时未充分考虑`BIT`特性。解决方法涉及正确运用索引、理解`BIT`的存储和比较机制,以及合理创建索引以覆盖各种查询条件。通过`EXPLAIN`分析执行计划可帮助诊断和优化查询。
|
2月前
|
存储 关系型数据库 MySQL
"深入探索MySQL临时表:性能优化利器,数据处理的灵活之选"
【8月更文挑战第9天】MySQL临时表专为存储临时数据设计,自动创建与删除,仅在当前会话中存在,有助于性能优化。它分为本地临时表和全局临时表(通过特定逻辑模拟)。创建语法类似于普通表,但加TEMPORARY或TEMP关键字。适用于性能优化、数据预处理和复杂查询,需注意内存占用和事务支持问题。合理使用可大幅提升查询效率。
104 2
|
2月前
|
SQL 算法 Java
(二十六)MySQL分库篇:Sharding-Sphere分库分表框架的保姆级教学!
前面《MySQL主从原理篇》、《MySQL主从实践篇》两章中聊明白了MySQL主备读写分离、多主多写热备等方案,但如果这些高可用架构依旧无法满足业务规模,或业务增长的需要,此时就需要考虑选用分库分表架构。
1624 2
下一篇
无影云桌面