本文目录一览:
mysql表分区使用及详细介绍
一、分区概念
分区是将一个表分成多个区块进行操作和保存,从而降低每次操作的数据,提高性能。而对于应用来说则是透明的,从逻辑上看只有一张表,但在物理上这个表可能是由多个物理分区组成的,每个分区都是独立的对象,可以进行独立处理。
二、分区作用
- 可以逻辑数据分割,分割数据能够有多个不同的物理文件路径。
- 可以存储更多的数据,突破系统单个文件最大限制。
- 提升性能,提高每个分区的读写速度,提高分区范围查询的速度。
- 可以通过删除相关分区来快速删除数据。
- 通过跨多个磁盘来分散数据查询,从而提高磁盘I/O的性能。
- 涉及到例如SUM()、COUNT()这样聚合函数的查询,可以很容易的进行并行处理。
- 可以备份和恢复独立的分区,这对大数据量很有好处。
三、分区能支持的引擎
MySQL支持大部分引擎创建分区,如MyISAM、InnoDB等;不支持MERGE和CSV等来创建分区。同一个分区表中的所有分区必须是同一个存储引擎。值得注意的是,在MySQL8版本中,MyISAM表引擎不支持分区。
四、确认MySQL支持分区
从MySQL5.1开始引入分区功能,可以如下方式查看是否支持:
- 老版本用:
SHOW VARIABLES LIKE '%partition%';
- 新版本用:
show plugins;
五、分区类型
- RANGE分区:基于属于一个给定连续区间的列值,把多行分配给分区。 例如,可以将一个表通过年份划分成两个分区,2001-2010年、2011-2020年。
- LIST分区:类似于RANGE分区,LIST是列值匹配一个离散值集合中的某个值来进行选择。 比如根据字段把值为1、3、5的放到一起,2、4、6的另外放到一起。
- HASH分区:基于用户定义的表达式的返回值来进行选择分区,该表达式使用将要插入到表中的这些行的列值来进行计算,这个函数必须产生非负整数值。 通过HASH运算来进行分区,分布的比较均匀。
- KEY分区:类似于按HASH分区,由MySQL服务器提供其自身的哈希函数。 按照KEY进行分区类似于按照HASH分区。
六、分区创建注意事项
- 如果表中存在primary key 或者 unique key 时,分区的列必须是primary key或者unique key的一个组成部分,也就是说,分区函数的列只能从pk或者uk这些key中取子集。
- 如果表中不存在任何的primary key或者unique key,则可以指定任何一个列作为分区列。
- 5.5版本前的RANGE、LIST、HASH分区要求分区键必须是int;MySQL5.5及以上,支持非整形的RANGE和LIST分区,即:range columns 和 list columns (可以用字符串来进行分区)。
七、分区命名
- 分区的名字基本上遵循其他MySQL 标识符应当遵循的原则,例如用于表和数据库名字的标识符。应当注意的是,分区的名字是不区分大小写的。
- 无论使用何种类型的分区,分区总是在创建时就自动的顺序编号,且从0开始记录。
八、创建分区
1. RANGE分区:
CREATE TABLE `test01` (
`dayid` int(11) DEFAULT NULL,
`mac` varchar(32) NOT NULL DEFAULT '',
`dtype` varchar(50) NOT NULL DEFAULT ''
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50100 PARTITION BY LIST (dayid)
(PARTITION p20171205 VALUES IN (20171205) ENGINE = InnoDB,
PARTITION p20171204 VALUES IN (20171204) ENGINE = InnoDB,
PARTITION p20171206 VALUES IN (20171206) ENGINE = InnoDB,
PARTITION p20171207 VALUES IN (20171207) ENGINE = InnoDB) */
解读:以上为 uuid小于5时放到p0分区下,uuid大于5且小于10放到p1分区下,uuid大于10且小于15放到p2分区下,uuid大于15一直到最大值的存在p3分区下。
2. LIST分区:
CREATE TABLE tbl_test (
uuid INT NOT NULL,
title VARCHAR(20)
)
PARTITION BY List (uuid) (
PARTITION p0 VALUES in (1,2,3,5),
PARTITION p1 VALUES in (7,9,10),
PARTITION p2 VALUES in (11,15)
);
解读:以上为uuid等于1/2/3/5时放到p0分区,7/9/10放到p1分区,11/15放到p2分区。当使用insert into
时,如果uuid的值不存在p0/p1/p2分区时,则会插入失败而报错。
3. HASH分区:
HASH分区主要用来确保数据在预先确定数目的分区中平均分布。在RANGE分区和LIST分区中必须明确指定一个指定的列值或列值集合以指定应该保存在哪个分区中。而在HASH分区中,MySQL会自动完成这些工作,要做的只是基于将要被哈希的列值指定一个表达式,以及指定被分区的表将要被分割成的分区数量,如:
CREATE TABLE tbl_test (
uuid INT NOT NULL,
title VARCHAR(20)
)
PARTITION BY HASH (uuid) (
PARTITIONS 3
);
解读:MySQL自动创建3个分区,在执行insert into
时,根据插入的uuid通过算法来自动分配区间。
注意:
- 由于每次插入、更新、删除一行,这个表达式都要计算一次,这意味着非常复杂的表达式可能会引起性能问题,尤其是在执行同时影响大量行的运算(例如批量插入)的时候。
- 最有效率的哈希函数是只对单个表列进行计算,并且它的值随列值进行一致的增大或减小,因为这考虑了在分区范围上的“修剪”。也就是说,表达式值和它所基于的列的值变化越接近,就越能有效地使用该表达式来进行HASH分区。
3.1:线性HASH分区
线性HASH分区在“PARTITION BY”子句中添加“LINEAR”关键字。 线性HASH分区的优点在于增加、删除、合并和拆分分区将变得更加快捷,有利于处理含有极其大量数据的表。它的缺点在于各个分区间数据的分布不大可能均衡。
4. KEY分区
类似于HASH分区,HASH分区允许用户自定义的表达式,而KEY分区则不允许使用用户自定义的表达式;HASH分区只支持整数分区,KEY分区支持除了blob和text类型之外的其他数据类型分区。 与HASH分区不同,创建KEY分区表的时候,可以不指定分区键,默认会选择使用主键或唯一键作为分区键,没有主键或唯一键,就必须指定分区键。
CREATE TABLE tbl_test (
uuid INT NOT NULL,
title VARCHAR(20)
)
PARTITION BY LINEAR Key (uuid)
PARTITIONS 3;
解读:根据分区键来进行分区。
5. 子分区
子分区是分区表中,每个分区的再次分割,适合保存非常大量的数据。
CREATE TABLE tbl_test (
registerTime Date
)
PARTITION BY RANGE(YEAR(registerTime))
SUBPARTITION BY HASH (TO_DAYS(registerTime))
SUBPARTITIONS 2
(
PARTITION p0 VALUES LESS THAN (2017),
PARTITION p1 VALUES LESS THAN (2020),
PARTITION p2 VALUES LESS THAN MAXVALUE
);
解读:主分区使用RANGE按照年来进行分区,有3个RANGE分区。这3个分区中又被进一步分成了2个子分区,实际上,整个表被分成了3 * 2 = 6个分区。每个子分区按照天进行HASH分区。小于2017的放在一起,2017-2020的放在一起,大于2020的放在一起。 注意:
- 在MySQL5.1中,对于已经通过RANGE或LIST分区了的表在进行子分区是可能的。子分区既可以使用HASH分区,也可以使用KEY分区。这也被称为复合分区。
- 每个分区必须有相同数量的子分区。
- 如果在一个分区表上的任何分区上使用SUBPARTITION来明确定义任何子分区,那么就必须定义所有的子分区。
- 每个SUBPARTITION子句必须包含(至少)子分区的一个名字。
- 在每个子分区内,子分区的名字必须是惟一的,目前在整个表中,也要保持唯一。例如:
PARTITION BY RANGE(YEAR(registerTime))
SUBPARTITION BY HASH(TO_DAYS(registerTime))
(
PARTITION p0 VALUES LESS THAN (2017) (
SUBPARTITION s0,
SUBPARTITION s1
),
PARTITION p1 VALUES LESS THAN (2020) (
SUBPARTITION s2,
SUBPARTITION s3
),
PARTITION p2 VALUES LESS THAN MAXVALUE (
SUBPARTITION s4,
SUBPARTITION s5
)
)
子分区可以用于特别大的表,可以在多个磁盘间分配数据和索引。例如:
SUBPARTITION s0
DATA DIRECTORY = '/disk0/data'
INDEX DIRECTORY = '/disk0/idx'
,
,
SUBPARTITION s1
DATA DIRECTORY = '/disk1/data'
INDEX DIRECTORY = '/disk1/idx'
九、MySQL分区处理NULL值的方式
MySQL中的分区禁止空值NULL上没有进行处理,无论它是一个列值还是一个用户定义表达式的值,一般而言,在这种情况下MySQL把NULL视为0。如果你希望回避这种做法,你应该在设计表时声明列“NOT NULL”。
十、分区管理概述
可以对分区进行添加、删除、重新定义、合并或拆分等管理操作。
① RANGE和LIST分区的管理
- 删除分区语句如:
alter table tbl_test drop partition p0;
注意:- 当删除了一个分区,也同时删除了该分区中所有的数据。
- 可以通过
show create table tbl_test;
来查看新的创建表的语句。 - 如果是LIST分区的话,删除的数据不能新增进来,因为这些行的列值包含在已经删除了的分区的值列表中。
- 添加分区语句如:
alter table tbl_test add partition(partition p3 values less than(50));
注意:- 对于RANGE分区的表,只可以添加新的分区到分区列表的最高端。
- 对于LIST分区的表,不能添加已经包含在现有分区值列表中的任意值。
- 如果希望能不丢失数据的条件下重新定义分区,可以使用如下语句:
ALTER TABLE tbl_name REORGANIZE PARTITION partition_list INTO(partition_definitions)
- 拆分分区如:
或者如:ALTER TABLE tbl_name REORGANIZE PARTITION partition_list INTO(partition s0 values less than(5),partition s1 values less than(10));
ALTER TABLE tbl_name REORGANIZE PARTITION p0 INTO(partition s0 values in(1,2,3), partition s1 values in(4,5));
- 合并分区如:
ALTER TABLE tbl_name REORGANIZE PARTITION s0,s1 INTO(partition p0 values in(1,2,3,4,5));
- 拆分分区如:
- 删除所有分区,但保留数据,形式:
ALTER TABLE tbl_name remove partitioning;
② HASH和KEY分区的管理
- 减少分区数量语句如:
ALTER TABLE tbl_name COALESCE PARTITION 2;
- 添加分区数量语句如:
ALTER TABLE tbl_name add PARTITION partitions 2;
③ 其他分区管理语句
- 重建分区:类似于先删除保存在分区中的所有记录,然后重新插入它们,可用于整理分区碎片。如:
ALTER table tbl_name REBUILD PARTITION p2,p3;
- 优化分区:如果从分区中删除了大量的行,或者对一个带有可变长度的行(也就是说,有VARCHAR,BLOB或TEXT类型的列)做了许多修改,可以使用
ALTER TABLE tbl_name OPTIMIZE PARTITION
来收回没有使用的空间,并整理分区数据文件的碎片。如:ALTER TABLE tbl_name OPTIMIZE PARTITION p2,p3;
- 分析分区:读取并保存分区的键分布,如:
ALTER TABLE tbl_name ANALYZE PARTITION p2,p3;
- 检查分区:检查分区中的数据或索引是否已经被破坏,如:
ALTER TABLE tbl_name CHECK PARTITION p2,p3;
- 修补分区:修补被破坏的分区,如:
ALTER TABLE tbl_name REPAIR PARTITION p2,p3;
十、查看分区信息
- 查看分区信息:
select * from information_schema.partitions where table_schema='arch1' and table_name = 'tbl_test' \G;
- 查看分区上的数据:
select * from tbl_test partition(p0);
- 查看MySQL会操作的分区:
explain partitions select * from tbl_test where uuid = 2;
十一、局限性
- 最大分区数目不能超过1024,一般建议对单表的分区数不要超过50个。
- 如果含有唯一索引或者主键,则分区列必须包含在所有的唯一索引或者主键在内。
- 不支持外键。
- 不支持全文索引,对分区表的分区键创建索引,那么这个索引也将被分区。
- 按日期进行分区很合适,因为很多日期函数可以用。但是对字符串来说合适的分区函数不太多。
- 只有RANGE和LIST分区能进行子分区,HASH和KEY分区不能进行子分区。
- 临时表不能被分区。
- 分区表对于单条记录的查询没有优势。
- 要注意选择分区的成本,没插入一行数据都需要按照表达式筛选插入的分区。
- 分区字段尽量不要可以为null。
MySQL的数据文件有几种?扩展名分别是什么?
.frm
是表结构,.MYD
是数据,.MYI
是索引,如果用InnoDB只有.frm
数据和索引存在InnoDB的数据文件里。
默认MySQL的数据库是存放在...\MySQL\MySQL Server 5.5\data
文件夹下。一个数据库是一个目录,目录下一个表对应三个文件,文件名是表名,扩展名分别是.frm
、.MYD
、.MYI
(数据文件:.myd
)、(索引文件:.MYI
)、(表定义文件:.frm
)。
扩展资料:
普通索引(由关键字KEY
或INDEX
定义的索引)的任务是加快对数据的访问速度。因此,应该只为那些最经常出现查询条件(WHERE column =
)或排序条件(ORDER BY column
)中的数据列创建索引。只要有可能,就应该选择一个数据最整齐、最紧凑的数据列(如一个整数类型的数据列)来创建索引。
普通索引允许被索引的数据列包含重复的值。比如说,因为人有可能同名,所以同一个姓名在同一个“员工个人资料”数据表里可能出现两次或更多次。
参考资料来源:百度百科 - MySQL
mysql中的表空间的概念是逻辑概念还是物理概念
一、系统表空间
在 MySQL 数据目录下有一个名为 ibdata1
的文件,可以保存一张或者多张表。
923275 12M -rw-r----- 1 mysql mysql 12M 3月 18 10:42 ibdata1
这个文件就是 MySQL 的系统表空间文件,默认为 1 个,可以有多个,只需要在配置文件 my.cnf
里面这样定义即可。
innodb_data_file_path=ibdata1:200M;ibdata2:200M:autoextend:max:800M
系统表空间不仅可以是文件系统组成的文件,也可以是非文件系统组成的磁盘块,比如裸设备,定义也很简单:
innodb_data_file_path=/dev/nvme0n1p1:3Gnewraw;/dev/nvme0n1p2:2Gnewraw
系统表空间里都有些啥内容? 具体内容包括:double writer buffer、change buffer、数据字典(MySQL 8.0 之前)、表数据、表索引。 那 MySQL 为什么现在主流版本默认都不是系统表空间? 究其原因,系统表空间有三个最大的缺点: 原因 1:无法做到自动收缩磁盘空间,造成很大的空间浪费。即使它包含的表都被删掉,这部分空间也不会自动释放。
二、单表空间
单表空间不同于系统表空间,每个表空间和表是一一对应的关系,每张表都有自己的表空间。具体在磁盘上表现为后缀为 .ibd
的文件。比如表 t1
,对应的表空间文件为 t1.ibd
:
917107 96K -rw-r----- 1 mysql mysql 96K 3月 18 16:13 t1.ibd
单表空间如何应用到具体的表呢?
有两种方式:
方式 1:在配置文件中开启。在配置文件中开启单表空间设置参数 innodb_file_per_table
,这样默认对当前库下所有表开启单表空间。
innodb_file_per_table=1
另外也可以直接建表时指定单表空间:
CREATE TABLE t1 (id int, r1 char(36)) TABLESPACE innodb_file_per_table;
Query OK, 0 rows affected (0.04 sec) 单表空间除了解决之前说的系统表空间的几个缺点外,还有其他的优点,详细如下:
TRUNCATE TABLE
操作比其他的任何表空间都快;- 可以把不同的表按照使用场景指定在不同的磁盘目录;
比如日志表放在慢点的磁盘,把需要经常随机读的表放在 SSD 上等。
Query OK, 0 rows affected (0.04 sec)CREATE TABLE ytt_dedicated (id int) DATA DIRECTORY = '/var/lib/mysql-files';
- 可以用
OPTIMIZE TABLE
来收缩或者重建经常增删改查的表。一般过程是这样的:建立和原来表一样的表结构和数据文件,把真实数据复制到临时文件,再删掉原始表定义和数据文件,最后把临时文件的名字改为和原始表一样的。
三、通用表空间
通用表空间先是出现在 MySQL Cluster 里,也就是 NDB 引擎。从 MySQL 5.7 引入到 InnoDB 引擎。通用表空间和系统表空间一样,也是共享表空间。每个表空间可以包含一张或者多张表,也就是说通用表空间和表之间是一对多的关系。