根据经验,Mysql表数据一般达到百万级别,查询效率会很低,容易造成表锁,甚至堆积很多连接,直接挂掉;水平分表能够很大程度较少这些压力。

1.按时间分表

这种分表方式有一定的局限性,当数据有较强的实效性,如微博发送记录、微信消息记录等,这种数据很少有用户会查询几个月前的数据,如就可以按月分表。
2.按区间范围分表

一般在有严格的自增id需求上,如按照user_id水平分表:
table_1  user_id从1~100w
table_2  user_id从101~200w
table_3  user_id从201~300w
...
3.hash分表

通过一个原始目标的ID或者名称通过一定的hash算法计算出数据存储表的表名,然后访问相应的表。
按如下分10张表:

function get_hash_table($table, $userid)
{
$str = crc32($userid);

if ($str < 0) {
$hash = "0" . substr(abs($str), 0, 1);
} else {
$hash = substr($str, 0, 2);
}

return $table . "_" . $hash;
}

echo get_hash_table('message', 'user18991'); //结果为message_10
echo get_hash_table('message', 'user34523'); //结果为message_13

另外,介绍我现在就是采用简单的取模分表:

/**
* @param string $table_name 表名
* @param int $user_id 用户id
* @param int $total 分表总数
*/
function hash_table($table_name, $user_id, $total)
{
return $table_name . '_' . (($user_id % $total) + 1);
}

echo hash_table("artice", 1234, 5); //artice_5
echo hash_table("artice", 3243, 5); //artice_4

4.利用merge存储引擎分表

感觉merge存储引擎类似sql中union的感觉,但是查询效率不高。
如下举例,拥有1000w记录的old_user表分表:
(1)创建new_user表使用merge存储引擎

mysql> CREATE TABLE IF NOT EXISTS `user1` (
->   `id` int(11) NOT NULL AUTO_INCREMENT,
->   `name` varchar(50) DEFAULT NULL,
->   `sex` int(1) NOT NULL DEFAULT '0',
->   PRIMARY KEY (`id`)
-> ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
Query OK, 0 rows affected (0.05 sec)

mysql> CREATE TABLE IF NOT EXISTS `user2` (
->   `id` int(11) NOT NULL AUTO_INCREMENT,
->   `name` varchar(50) DEFAULT NULL,
->   `sex` int(1) NOT NULL DEFAULT '0',
->   PRIMARY KEY (`id`)
-> ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
Query OK, 0 rows affected (0.01 sec)

mysql> INSERT INTO `user1` (`name`, `sex`) VALUES('张映', 0);
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO `user2` (`name`, `sex`) VALUES('tank', 1);
Query OK, 1 row affected (0.00 sec)

mysql> CREATE TABLE IF NOT EXISTS `new_user` (
->   `id` int(11) NOT NULL AUTO_INCREMENT,
->   `name` varchar(50) DEFAULT NULL,
->   `sex` int(1) NOT NULL DEFAULT '0',
->   INDEX(id)
-> ) TYPE=MERGE UNION=(user1,user2) INSERT_METHOD=LAST AUTO_INCREMENT=1
;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> select id,name,sex from new_user;
+----+--------+-----+
| id | name   | sex |
+----+--------+-----+
|  1 | 张映 |   0 |
|  1 | tank   |   1 |
+----+--------+-----+
2 rows in set (0.00 sec)

mysql> INSERT INTO `new_user` (`name`, `sex`) VALUES('tank2', 0);
Query OK, 1 row affected (0.00 sec)

mysql> select id,name,sex from user2
-> ;
+----+-------+-----+
| id | name  | sex |
+----+-------+-----+
|  1 | tank  |   1 |
|  2 | tank2 |   0 |
+----+-------+-----+
2 rows in set (0.00 sec)

(2)我old_user数据进行分表:

INSERT INTO user1(user1.id,user1.name,user1.sex) SELECT
(user.id,user.name,user.sex)FROM old_user where user.id <= 5000000
INSERT INTO user2(user2.id,user2.name,user2.sex) SELECT
(user.id,user.name,user.sex)FROM old_user where user.id > 10000000

这种方案最大的好处是,几乎不用动业务代码。

原文链接:http://www.4u4v.net/mysql-common-sub-table-level-technical-solutions.html

MySQL常见水平分表技术方案的更多相关文章

  1. mysql 水平分表技术

    这里做的是我的一个笔记. 水平分表比较简单, 理解就是: 合并的表使用的必须是MyISAM引擎 表的结构必须一致,包括索引.字段类型.引擎和字符集 数据表 user1 CREATE TABLE `us ...

  2. mysql使用MRG_MyISAM(MERGE)实现水平分表

    在MySQL中数据的优化尤其是大数据量的优化是一门很大的学问,当然其它数据库也是如此,即使你不是DBA,做为一名程序员掌握一些基本的优化信息,也可以让你在自己的程序开发中受益匪浅.当然数据库的优化有很 ...

  3. TDSQL MySQL版基本原理-水平分表 读写分离 弹性扩展 强同步

    TDSQL MySQL版(TDSQL for MySQL)是部署在腾讯云上的一种支持自动水平拆分.Shared Nothing 架构的分布式数据库.TDSQL MySQL版 即业务获取的是完整的逻辑库 ...

  4. mysql中的优化, 简单的说了一下垂直分表, 水平分表(有几种模运算),读写分离.

    一.mysql中的优化 where语句的优化 1.尽量避免在 where 子句中对字段进行表达式操作select id from uinfo_jifen where jifen/60 > 100 ...

  5. mysql数据库的水平分表与垂直分表实例讲解

    mysql语句的优化有局限性,mysql语句的优化都是围绕着索引去优化的,那么如果mysql中的索引也解决不了海量数据查询慢的状况,那么有了水平分表与垂直分表的出现(我就是记录一下自己的理解) 水平分 ...

  6. Sharding-JDBC 实现水平分表

    1.搭建环 (1) 技术: SpringBoot2.2.1+ MyBatisPlus + Sharding-JDBC + Druid 连接池(2)创建 SpringBoot 工程

  7. mycat水平分表

    和垂直分库不同,水平分表,是将那些io频繁,且数据量大的表进行水平切分. 基本的配置和垂直分库一样,我们需要改的就是我们的 schema.xml和rule.xml文件配置(server.xml不用做任 ...

  8. 玩转SpringBoot之整合Mybatis拦截器对数据库水平分表

    利用Mybatis拦截器对数据库水平分表 需求描述 当数据量比较多时,放在一个表中的时候会影响查询效率:或者数据的时效性只是当月有效的时候:这时我们就会涉及到数据库的分表操作了.当然,你也可以使用比较 ...

  9. mycat - 水平分表

    相对于垂直拆分的区别是:垂直拆分是把不同的表拆到不同的数据库中,而水平拆分是把同一个表拆到不同的数据库中.水平拆分不是将表的数据做分类,而是按照某个字段的某种规则来分散到多个库之中,每个表中包含一部分 ...

随机推荐

  1. windows服务器入门 php的安装

    下载PHP安装包(下载地址: http://windows.php.net/download/ ),本文档以5.3版本为例,选择如下图对应的安装包: 下载完成后进行安装PHP,需要选择Web服务时,选 ...

  2. js删除array数组中元素

    for(var i = 0; i < array.length; i++) { if(-1 != array[i]) { array.splice(i, 1); i--; } } 上面if就是判 ...

  3. Nginx 413 Request Entity Too Large

    用户上传图片的时候,报错. 发现,原来是图片太大导致. 咦?后台配置图片支持5M啊? 哦!原来是Nginx配置问题. Nginx默认支持1M的POST数据! 修改Nginx配置! 修改nginx.co ...

  4. PCL学习(二)三维模型转点云 obj转pcd----PCL实现

    #include <pcl/io/io.h> #include <pcl/io/pcd_io.h> #include <pcl/io/obj_io.h> #incl ...

  5. ARTS第六周打卡

    Algorithm : 做一个 leetcode 的算法题 1.合并两个排序链表 2.树的子结构 3.二叉树的镜像 4.包含Min函数的栈 5.栈的压入.弹出 6.二叉搜索树的后序遍历 7.从上往下打 ...

  6. Django Simple Captcha的使用

    Django Simple Captcha的使用 1.下载Django Simple Captcha django-simple-captcha官方文档地址 http://django-simple- ...

  7. glib系列2 APP编译

    编译命令 gcc main.c `pkg-config --cflags glib-2.0 --libs glib-2.0` 头文件 $ ls /usr/local/include/glib-2.0/ ...

  8. go实现简单的tcp编程

    服务端的代码 package main import ( "fmt" "net" ) func main () { fmt.Println("star ...

  9. C#操作DOS命令,并获取处理返回值

    // /*---------------- // // 文件名:Method // // 文件功能描述: // //    使用 ADB 来进行安卓设备与PC端之间的文件交互,具体adb命令操作请百度 ...

  10. ubuntu14.04

    14.10显卡驱动有问题 1.恢复启动引导菜单:启动盘 -> 运行到分区之前,不要分区 -> shift+f10 进入dos -> bootsec /fixmbr ->关闭重启 ...