• 分区分表分库


     

     

     
     

    分区(加快访问速度)

    什么时候分区?

    一张表的查询速度已经慢到影响使用的时候。

    • sql经过优化
    • 数据量大(表的大小超过2GB,一般单表撑死1000万条)
    • 表中的数据是分段的(表中包含历史数据,新的数据被增加都新的分区中)
    • 对数据的操作往往只涉及一部分数据,而不是所有的数据

    从应用程序的角度来看,分区后的表与非分区表完全相同,使用 SQL DML 命令访问分区后的表时,无需任何修改。

    CREATE TABLE sales (
    
    id INT AUTO_INCREMENT,
    
    amount DOUBLE NOT NULL,
    
    order_day DATETIME NOT NULL,
    
    PRIMARY KEY(id, order_day)
    
    ) ENGINE=Innodb
    
    PARTITION BY RANGE(YEAR(order_day)) (
    
    PARTITION p_2010 VALUES LESS THAN (2010),
    
    PARTITION p_2011 VALUES LESS THAN (2011),
    
    PARTITION p_2012 VALUES LESS THAN (2012),
    
    PARTITION p_catchall VALUES LESS THAN MAXVALUE);
    

    Mysql的主从模式(分库分表前的解决方案)

    面对越来越多的请求,我们将数据库的写操作和读操作进行分离, 使用多个从库副本(Slaver Replication)负责读,使用主库(Master)负责写, 从库从主库同步更新数据,保持数据一致。架构上就是数据库主从同步。 从库可以水平扩展,所以更多的读请求不成问题。

    但是当用户量级上来后,写请求越来越多,该怎么办加一个Master是不能解决问题的, 因为数据要保存一致性,写操作需要2个master之间同步,相当于是重复了,而且更加复杂。(需要分布式一致性算法维护)

    这时就需要用到分库分表(sharding),对写操作进行切分。

    数据库的“写”(写10000条数据到oracle可能要3分钟)操作是比较耗时的。但是数据库的“读”(从oracle读10000条数据可能只要5秒钟)


    垂直切分和水平切分(分库分表)

    垂直分表(同一表的冷热数据拆分)

    也就是“大表拆小表”,基于列字段进行的。一般是表中的字段较多,将不常用的, 数据较大,长度较长(比如text类型字段)的拆分到“扩展表“。 一般是针对那种几百列的大表,也避免查询时,数据量太大造成的“跨页”问题。

    将访问频次低的商品描述信息单独存放在一张表中,访问频次较高的商品基本信息单独放在一张表中。

    MySQL底层是通过数据页存储的,一条记录占用空间过大会导致跨页,造成额外的性能开销。

    • 通常我们按以下原则进行垂直拆分:

    (1)把不常用的字段单独放在一张表;
    (2)把text,blob等大字段拆分出来放在附表中;
    (3)经常组合查询的列放在一张表中;

    垂直分库

    通过垂直分表性能得到了一定程度的提升,但是还没有达到要求,并且磁盘空间也快不够了,因为数据还是始终限制在一台服务器,库内垂直分表只解决了单一表数据量过大的问题,但没有将表分布到不同的服务器上,因此每个表还是竞争同一个物理机的CPU、内存、网络IO、磁盘。

    垂直分库针对的是一个系统中的不同业务进行拆分,比如用户User一个库,商品Producet一个库,订单Order一个库。 切分后,要放在多个服务器上,而不是一个服务器上。

    水平分表分库

    • RANGE

    从0到10000一个表,10001到20000一个表;

    • HASH取模

    一个商场系统,一般都是将用户,订单作为主表,然后将和它们相关的作为附表,这样不会造成跨库事务之类的问题。 取用户id,然后hash取模,分配到不同的数据库上。

    比如美团的分库分表的方案是32个数据库实例,通过userId进行取模的话就是,将UserId后面4位模32然后丢到32个数据库中,同时又将UserId后面4位除以32再mod32丢到32张表里面,这样就有1024张表,然后线上部署8个主从实例,每个实例4个数据库。

    如果频繁用到的查询条件中不带sharding key时,将会导致无法定位数据库,从而需要同时向多个库发起查询,再在内存中合并数据,取最小集返回给应用,分库反而成为拖累。

    • 地理区域

    比如按照华东,华南,华北这样来区分业务,七牛云应该就是如此。

    • 时间

    按照时间切分,就是将6个月前,甚至一年前的数据切出去放到另外的一张表,因为随着时间流逝,这些表的数据 被查询的概率变小,所以没必要和“热数据”放在一起,这个也是“冷热数据分离”。


    分库分表后面临的问题

    • 事务支持

    分库分表后,就成了分布式事务了。如果依赖数据库本身的分布式事务管理功能去执行事务,将付出高昂的性能代价; 如果由应用程序去协助控制,形成程序逻辑上的事务,又会造成编程方面的负担。

    • 多库结果集合并(group by,order by)

    • 跨库join(水平分库能join,垂直分库不行)

    分库分表后表之间的关联操作将受到限制,我们无法join位于不同分库的表,也无法join分表粒度不同的表, 结果原本一次查询能够完成的业务,可能需要多次查询才能完成。

    粗略的解决方法:
    (1)全局表:基础数据,所有库都拷贝一份。
    (2) 字段冗余:这样有些字段就不用join去查询了。
    (3)系统层组装:分别查询出所有,然后组装起来,较复杂。

     
    image.png

    分布式下怎么保障ID唯一

    1. 利用数据库集群并设置相应的步长(Flickr方案)
      优点:高可用、ID较简洁。 缺点:需要单独的数据库集群。

    2. Twitter Snowflake
      优点:高性能高可用、易拓展。 缺点:需要独立的集群以及ZK。

    3. 带有业务属性的方案: > 时间戳+用户标识码+随机数

    有下面几个好处:

    (1)方便、成本低。
    基本无重复的可能。
    (2)自带分库规则,这里的用户标识码即为用户ID的后四位,在查询的场景下,只需要订单号就可以匹配到相应的库表而无需用户ID,只取四位是希望订单号尽可能的短一些,并且评估下来四位已经足够。
    (3)可排序,因为时间戳在最前面。

    欢迎关注微信公众号:shoshana

  • 相关阅读:
    《单元测试之道C#版——使用NUnit》测试哪些内容 RightBICEP
    《领域驱动设计》读书笔记(三) 消化知识
    法雷数列浅谈 RL
    四种常用最短路径算法模板 RL
    PIG 学习笔记1
    readme
    隐藏系统队伍框架
    关于时间的一些函数
    两个作用相同的宏.
    自动拾取确认,自动复活确认
  • 原文地址:https://www.cnblogs.com/shoshana-kong/p/14007626.html
Copyright © 2020-2023  润新知