MySQL 分库分表
https://www.jianshu.com/p/7aec260ca1a2
前言:
针对大量数据时,导致对数据库的执行变慢。所以要进行数据库优化。
之间了解的优化就是些简单的操作,如:
- 加索引啊,为经常查询的字段加上索引,可以提升查询时间(但是如果是经常执行插入、更新、删除的表就容易带来额外的开销,因为要动态的维护索引,所以就会降低数据库性能)
- sql语句优化,老生常谈的查询时不要尽量完整写出索要查询的字段啊,不要图方便用*,这样就是全文查询和几个字段上查询带来区别上的差异,自己写个sql测试下速度快乐三分一吧,快六万的数据,随便编的数据,实际可以自行测试。
- 只需要查询一条数据的话使用上limit, 不要查询出所有符合要求的数据后再取一条,因为使用limit只要查询到符合要求的就会停止查询
- 条件查询再以下几种情况下会放弃索引而采用全表扫描
- 对字段进行null判断
- != 和 <>
- or
- 对字段进行表达式操作(函数)
- 在设计表字段的时候要考虑好,选择适合的数据类型,影响到查询效率,对存储开销进行考虑。
- 游标的使用(我也不知道游标是啥!记录下,下次学习)
内容:
言归正传,当数据库存储大量数据时就必然会遇到性能上的瓶颈,Mysql单库5000万,单表500~1000万时性能会变差(数据从某篇博文里看到的,做个参考吧!)
数据库的拆分主要分为水平拆分和垂直拆分;
- 垂直拆分库就是将数据库中的表进行模块划分,比如分为用户信息的、业务详情、商品详情等,然后将每个模块的表分开存放在不同的数据库中,然后查找相应的表就对应相应的数据库去查询,这样就减缓了数据库的连接。最好是将数据库放置在不同的服务器上,才能在硬件磁盘读取上有所优化
- 垂直分表,就是将多字段的表进行字段拆分成多个表
- 水平拆分表,是将一张表中的数据分散存储在多张表当中
以上的拆分方式容易带来许多问题,如下:
- 分布式事物处理
- 跨库的join连接
- 横向的扩容
- 结果集 、排序问题
这些都或多或少会带来代码实现上的问题。
接下来讲一下实际中的三种方法
- Mysql集群
- 原理:将数据同时存放在多个数据库服务器上,分散请求访问数据库
- 优点:是降低sql等待时间
- 缺点:sql的执行时间不会改善、对硬件的需求大
- 水平分表
- 原理:在设计初期的时候,将预计会存放大量数据的表拆分成若干小表进行存放
- 实例:假如一张用户表,将用户id通过从hash的方式分散的存储在其中的之歌小表中,在获取用户信息时就去对应的表中获取即可
-
function get_table_name($table_name,$user_id) { $str = crc32($user_id); if($str>0){ $num = substr($str,0,2); }else{ $num = '0'.substr($str,0,1); } return $table_name.'_'.$num; } $table_name = get_table_name('user','user213124');
- 优点:减少一张表中的数据量,可以加快sql的执行速度
- 缺点:在代码实现上,定义好了分散存储小表的规则就不好在更改,不然就是大工程量了
- merge存储引擎
- 原理:类似视图的概念吧,就是在原先的开发中将数据存放在了同一个表中,然而在后台的运营中数据量的加大导致运行速度缓慢。此时如果将该表水平进行拆分成多个表,那么代码上的sql就得大改咯,所以就要借助merge存储引擎了,merge存储引擎可以将多个表结构相同且为myisam表形成一个大表,让代码继续执行大表就可以。(当然还是需要改代码)
- Mysql集群
我实际使用过第二种水平分表的方式进行,是在项目执行一段时间之后才进行水平分表的。(写了个脚本将大表中的数据执行分表规则相应的存放到相应的小表当中);对于数据库集群还没条件尝试,所以现在学习下第三种方法merge存储引擎,坐下笔记
CREATE TABLE log_merge ( dt DATETIME NOT NULL, info VARCHAR(100) NOT NULL, INDEX(dt) ) ENGINE = MERGE UNION = (log_2004, log_2005, log_2006, log_2007);
如上图:创建一个表,engine设置为merge,将log_2004~log_2007之间的表规整起来形成一个逻辑单元。
还可以设置INSERT_METHOD属性,参数有0、first、last标记插入数据时实际存放的表,依次是不允许插入、在第一张表插入、在最后一张表插入。