Mysql 基础课十一:分库分表

需求

  1. 因为数据库单表容量超过 1000 万,性能会变差,并且单节点 Mysql 实例支持的并发也有限,所以需要对数据进行切分,有分库和分表的手段;
	分库,将并发访问高的表,单独放在一个库中,这样提高了并发性能,但无法解决单表过大的问题
	分表,选择合适的分片键,对表进行拆分
	如果单笔超过 1000 亿条数据,建议使用 Hadoop 等大数据工具
  1. 分库分表有几个原则,尽量不要分表,选择合适的分片键,分片键是查询的热点条件,且能比较均匀的划分数据,字典表进行数据冗余,合理划分数据,将关联表的关联数据划分在同一分片;

  2. 引入多个数据库后,就需要多数据源的管理,并且还需要非分片字段的查询,join 操作和分布式事务的支持,为此可以引入一个中间层 proxy,使得应用层不用关心分库分表后的细节处理,如 Mycat;

Mycat

  1. 中间代理层 MyCat,是对 SQL 进行分析,确定分片,将 SQL 发往真实数据库执行,单节点无法返回结果的,还需要多节点查询,数据处理后返回给上层应用;

  2. MyCat 使用 schema.xml 来定义物理库和表,使用 server.xml 定义系统配置信息,使用 rule.xml 定义分片规则等信息;
    schema.xml:管理Mycat的逻辑库,表,分片规则,dataNode以及DataSource

	// schema.xml
    <schema>:逻辑库,和Mysql中的database的概念相同
    <table>:逻辑表
    <dataNode>:标识一个数据节点
    <dataHost>:具体的数据库实例
	// server.xml
    <user>:定义登录mycat的用户和权限
	// rule.xml:定义分片规则

分片查询

  1. 如果查询没有分片字段,
	where 子句,MyCat 需要去每一个节点都做一次查询
	limit n 操作,同样需要去所有节点查询,并随机返回一份
	order by col_name limit n 操作,需要将所有节点的查询结果汇总,使用排序算法,排序后返回
	对于 limit m, n 操作,会改写为 limit 0,m+n,节点查询结果汇总后,根据 limit m, n 返回,这类查询,性能影响极大
  1. limit m, n 的一种改造思路,是每次查询,获取上一次查询的排序字段的最大值 last_max,这样下次查询,直接使用 limit n where field > last_max;

  2. 使用 left join 或者 right join 时,on 子句的匹配条件会优先执行,where 条件在最后执行,所以尽可能在 on 语句中进行条件判断;

  3. 对于某些全局表,如字典表,Mycat 采用冗余的方式在每个节点缓存,避免一定的跨库 join 操作;

	// 配置全局表
	<table name="company" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" />
  1. 分片策略上,可以将经常关联的几张表,根据关联关系,将关联数据放在一个分片上,这样就能实现局部 join 操作;
	// 例如:customer 和 orders 表是两个分片表,配置两张表的关联关系 o.customer_id=c.id 来放在同一分片
	<table name="customer" dataNode="dn1,dn2" rule="sharding-by-intfile">
    	<childTable name="orders" joinKey="customer_id" parentKey="id"/>
	</table>

自增 id

1…

分区表

  1. 分区表,对引擎层来说,是多个表,对 Server 层来说,是 1 个表;information_schema 库的表 partitions 保存该库的所有分区信息;

  2. 分区表有几个特点,首先第一次打开分区表,需要访问所有的分区,其次,所有分区会共用一个 MDL 锁,这样访问一个分区会阻塞所有分区的更新操作,最后,会根据分区的规则,对应的语句只访问必要的分区;

  3. 如果使用分区表,建议不要创建太多的分区,并且往往可以用手工分表来代替分区表,避开了分区表的一些弊端,分区表的优点是对业务透明,能扩展表容量;

  4. 分区表,根据分区规则,分为 range,list,hash,key 几种分区模式,且分区键只能是主键或唯一字段;

	// 根据birth_date的 hash 值的分为6个分区的表
	create table(
		emp_id int, 
		salary decimal(7,2), 
		birth_date date)engine = innodb 
    partition by HASH(MONTH(birth_date)) partitions 6 
    // 增加8个分区
    alter table t add partition partitions 8
    // 会删除分区和分区表中的数据
    alter table t drop partition p2; 
    // 拆分分区
    alter table t reorganize partition p3 into (...) 

你可能感兴趣的:(Mysql)