当前位置: 首页 > 科技观察

本文彻底搞懂MySQL分区

时间:2023-03-19 01:35:35 科技观察

1。InnoDB逻辑存储结构首先介绍一下InnoDB逻辑存储结构和区域的概念。它的所有数据都在逻辑上存储在表空间中,表空间由段、区、页组成。Segment就是上图中的段区域。常见的段包括数据段、索引段、回滚段等。在InnoDB存储引擎中,段的管理是由引擎自己完成的。该区域就是上图中的extent区域。该区域是由连续页面组成的空间。无论页面大小如何变化,该区域的大小默认始终为1MB。为了保证zone中page的连续性,InnoDB存储引擎一次从磁盘申请4-5个zone。InnoDB页面的默认大小为16kb,即一个zone共有64(1MB/16kb=16)个连续的页面。在每个段的开始,使用32页(page)的分片页来存储数据,这些页用完之后,再请求64个连续的页。这样做的目的是对于一些小表或者undosegments,可以开始申请一个小空间,节省磁盘开销。页面就是上图中的页面区域,也可以称为块。页是InnoDB磁盘管理的最小单位。默认大小为16KB,可以通过参数innodb_page_size设置。常见的页类型有:数据页、撤销页、系统页、事务数据页、插入缓冲区位图页、插入缓冲区空闲列表页、未压缩二进制大对象页、压缩二进制大对象页等。  2。PartitioningOverviewPartitioning这里说的分区,这个“区域”不是“区域”,这里分区的意思是把同一张表中不同行的记录分配给不同的物理文件,几个分区就是几个.idb文件,不是我们刚才提到的区域。MySQL在5.1中增加了对水平分区的支持。分区将表或索引分成更小、更易于管理的部分。每个区域都是独立的,可以独立处理或作为更大对象的一部分进行处理。这是MySQL支持的功能,业务代码不用改。要知道MySQL是面向OLTP的数据,不像TIDB等其他DB。那么分区的使用要非常小心,如果不清楚如何使用分区可能会对性能产生负面影响。MySQL数据库的分区是部分分区索引。分区存储数据和索引。也就是说,每个zone的聚集索引和非聚集索引都放在各自的zone中(不同的物理文件)。目前,MySQL数据库不支持全局分区。无论何种分区类型,如果表中存在主键或唯一索引,则分区列必须是唯一索引的组成部分。3、分区类型目前MySQL支持几种分区类型,RANGE分区、LIST分区、HASH分区、KEY分区。如果表有主键或唯一索引,分区列必须是唯一索引的组成部分。十个实战九个使用RANGE分区。RANGE分区RANGE分区是实际中最常用的分区类型。行数据根据属于给定连续区间的列值放入分区中。但请记住,当插入的数据不在分区中定义的值时,将抛出异常。RANGE分区主要用于对日期列进行分区,如交易表、销售表等,数据可以按照年份和月份进行存储。如果在唯一索引中对日期类型的数据进行分区,那么要注意,优化器只能优化YEAR()、TO_DAYS()、TO_SECONDS()、UNIX_TIMESTAMP()等函数。实战中可以使用int类型,所以只存yyyyMM。不用再担心功能了。CREATETABLE`m_test_db`.`Order`(`id`INTNOTNULLAUTO_INCREMENT,`partition_key`INTNOTNULL,`amt`DECIMAL(5)NULL,PRIMARYKEY(`id`,`partition_key`))PARTITIONBYRANGE(partition_key)PARTITIONS5(PARTITIONpart0VALUESLESSTHAN(201901)PARTITIONpart1VALUESLESTHAN(201902),PARTITIONpart2VALUESLESSTHAN(201903),PARTITIONpart3VALUESLESSTHAN(201904),PARTITIONpart4VALUESLESSTHAN(201905));这时候我们插入一些数据INSERTINTO`m_test_db`.`Order`(`id`,`am_partition_key)VA`,`LU('1','201901','1000');INSERTINTO`m_test_db`.`Order`(`id`,`partition_key`,`amt`)VALUES('2','201902','800');INSERTINTO`m_test_db`.`Order`(`id`,`partition_key`,`amt`)VALUES('3','201903','120??0');现在我们查看一下,发现SQL优化器只使用EXPLAINPARTITION命令搜索对应的区域,并不会搜索所有的分区。如果SQL语句有问题,会搜索所有区域。会很危险。因此,对表进行分区后,select语句必须使用分区键。下面这3种不是很常用,就一笔带过。LIST分区LIST分区和RANGE分区很相似,只是分区列的值是离散的,不是连续的。LIST分区使用VALUESIN,因为每个分区的值都是离散的,所以只能定义值。HASH分区说到哈希,目的很明显。将数据均匀分布到预先定义的分区中,保证每个分区的数量大致相同。KEY分区KEY分区与HASH分区类似,只是HASH分区使用用户自定义函数进行分区,而KEY分区使用数据库提供的函数进行分区。4.分区和性能一项技术用了不一定带来好处。比如显式锁功能比内置锁功能强大,玩不好可能会导致很糟糕的情况。分区也是如此。这并不意味着分区数据库会运行得更快。分区可能会提高一些SQL语句的性能,但分区主要用于数据库的高可用管理。数据库应用分为两类,一类是OLTP(OnlineTransactionProcessing),一类是OLAP(OnlineAnalyticalProcessing)。为OLAP应用分区确实可以提高查询性能,因为一般的分析需要返回大量的数据。如果按时间分区,比如一个月内的用户行为等数据,只需要扫描对应的分区即可。在OLTP应用程序中,分区应该更加小心。通常一个大表的10%的数据是不会获取到的,大部分可以通过索引返回几条数据。比如一个1000w数据量的表,如果一条select语句使用了辅助索引,但是没有使用partitionkey。那么结果就尴尬了。如果1000w的B+树的高度是3,那么现在有10个分区。那你不是要(3+3)*10逻辑IO吗?(3个聚簇索引,3个二级索引,10个分区)。所以在OLTP应用中请谨慎使用分区表。在日常开发中,如果想查看sql语句的分区查询结果,可以使用explainpartitions+selectsql获取。partitions标识哪些分区已被移动。mysql>explainpartitionsselect*fromTxnListwherestartTime>'2016-08-2500:00:00'andstartTime<'2016-08-2523:59:00';+----+------------+--------------------+------------+--------+--------------+------+--------+------+------+------------+|id|select_type|table|partitions|type|possible_keys|key|key_len|ref|rows|Extra|+----+------------+------------------+------------+-----+-------------+------+----------+------+------+------------+|1|SIMPLE|ClientActionTrack|p20160825|ALL|NULL|NULL|NULL|NULL|33868|Usingwhere|+----+------------+------------------+------------+------+------------+-----+------------+------+------+------------+1rowinset(0.00sec)