一个库一个目录
对于分区分表 都可以进行横向(按表字段分),纵向分(按数据行分),此文暂时值考虑横向分。
对于分库:分库
分区和分表类似,把原本的一个数据量很大的表,根据规则分成很多块。这些块可以跨磁盘分布。突破单磁盘IO的限制。
分表是建立多张子表,每张表的表字段相同,根据映射算法把数据分到不同子表。数据文件只能在一个磁盘上,一个数据库实例中。
(2)只能在一个数据库实例中,只能在一个磁盘中,内存加载和计算只能在一台机器中。
(3)要事先预估数据量,后期可能会随着数据的扩容重新扩展映射表。
(4)对于跨子表的统计查询,会比较复杂。
分库 可以突破服务器单节点内存,和计算的的限制。具体可以通自定义程序逻辑实现。根据场景自己实现即可。
如:主从备份读写分离,数据库按业务进行分(纵向)。把一张很大的表横向切分 并放在不同的库中(映射方法类似于分表分区)。
分库要考虑跨库多表查询的问题。
要考虑分布式事务的问题。
主要可以利用多个磁盘,提高IO性能。
分区把一个表数据和索引存储到多个不同的地方,跨磁盘,(可以跨文件系统,前提是当前系统可以看到此文件系统),可以指定每个分区文件存储的位置。
分区可以分为垂直分区(对一个大表,拆字段分别放在不同分区),和水平分区(把特定的某些行分开存放)。目前mysql只支持水平分区。
指定分区所在磁盘的文件:https://blog.csdn.net/xuheng8600/article/details/79817040
分区具体命令操作:https://blog.csdn.net/qq_35726305/article/details/81221721
分区可以调整(如把一个分区调整为2个),可以合并(如把两个分区合并为一个),可以追加,可以删除
在做分区前,也要先预估数据量,然后分为几个区。最好是按照时间分区,比如一年一个分区,这样就不用预估多少个分区,每一年开始就追加一个分区即可
根据所使用的不同分区规则可以分成几大分区类型。
RANGE 分区:
基于属于一个给定连续区间的列值,把多行分配给分区。
LIST 分区:
类似于按RANGE分区,区别在于LIST分区是基于列值匹配一个离散值集合中的某个值来进行选择。
HASH分区:
基于用户定义的表达式的返回值来进行选择的分区,该表达式使用将要插入到表中的这些行的列值进行计算。这个函数可以包含MySQL中有效的、产生非负整数值的任何表达式。
KEY
分区:类似于按HASH分区,区别在于KEY分区只支持计算一列或多列,且MySQL服务器提供其自身的哈希函数。必须有一列或多列包含整数值。
复合分区:
基于RANGE/LIST 类型的分区表中每个分区的再次分割。子分区可以是 HASH/KEY 等类型。
create table t5 (a varchar(20) not null,b varchar(11) not null,id int not null) partition by range(id)
(
partition s1 values less than(2000000),
partition s2 values less than(4000000),
partition s3 values less than(10000000)
)
可见分为三个区后,在mysql的数据库目录下,多了三个ibd分区的文件,和一个frm的表信息文件。
不使用分区列查询,可以看到用到了三个分区
注意此处测试时,我所有分区都在一个磁盘,所以不考虑多个磁盘会提升IO性能的问题。
test1是没有分区的表,t5是分为三个区的表(按照id:<2000000,<4000000,<10000000)。两个表都没有索引,数据都一样,总量都为6291456条。
两个 表格式如下
可以看到,条件如果没有分区列,则会查询三个分区。速度上两者差不多。
在一个分区内的数据查询
可以看到只使用一个分区。速度要比不分区要快的多。
数据跨两个分区
可以看到id<2500000的数据跨了两个分区。同样比不分区要快。
跨所有分区
当条件id<4500000时跨所有三个分区,速度上两者差不多。
分表有多种方式,目前我们只说两种。做分表前,最好要提前预估数据量(不然后面要增加子表需要重建映射关系),并根据数据量 确定使用的映射子表的算法。最好能够按年进行分表,这样就能很好的解决建多少张表的问题。
另外可以考虑一致性hash。
主要原理是利用MERGE引擎创建一个主表,把两张子表关联起来(方便总的统计查询)。这样只查询主表即可。但是由于主表插入的函数只有两个选项LAST或者FIRST(即插入到最后一个子表或者第一个子表)。因此需要自己再程序中创建映射子表的算法。
上述sql 中TYPE=MERGE表示使用MERGE存储引擎; UNION=(user1,user2) 表示要把两张表组合一起,INSERT_METHOD=NO 表示不允许插入主表。使用first或last值使得插入被相应地做在第一或最后一个表上。如果你没有指定insert_method选项,或你用一个no值指定该选,则表示不允许插入主表。
a1,a2,a3为子表,a为主表。数据文件如下
基于MERGE创建的分表,子表必须是myisam, 主表必须是mrg_myisam。此分表只有一个作用,就是利用MERGE合并表的方式,能够统计所有分表的信息(其实完全可以使用sql语句union all)。完全不建议使用。
通过预估数据量,指定数据映射算法,对每次增删改查操作映射到不同的子表上,减少查询数据量。