分区表-理论

分区表-理论目的分区表的主要目的是方便数据的维护,而不是提升MySQL数据库的性能。《高性能MySQL》中:分区的一个主要目的是将数据按照一个较粗的粒度分在不同的表中,这样做可以将相关的数据放在一起,另外

大家好,又见面了,我是你们的朋友全栈君。

目的

分区表的主要目的是方便数据的维护,而不是提升 MySQL 数据库的性能。

《高性能MySQL》中:分区的一个主要目的是将数据按照一个较粗的粒度分在不同的表中,这样做可以将相关的数据放在一起,另外,如果想一次批量删除整个分区的数据也会变得很方便。

定义

对用户来说,分区表是一个独立的逻辑表,但是底层由多个物理子表组成。实现分区的代码实际上是对一组底层表的句柄对象(Handle Object)的封装。对分区表的请求,都是通过句柄对象转化成对存储引擎的接口的调用。当前 MySQL 数据库支持的分区函数类型有 RANGE、LIST、HASH、KEY、COLUMNS。无论选择哪种分区函数,都要指定相关列成为分区算法的输入条件,这些列就叫“分区列”。

MySQL实现分区的方式——对底层表的封装——意味着索引也是按照分区的子表定义的,而没有全局索引。MySQL在创建表时使用PARTITION BY子句定义每个分区存放的数据。在执行查询的时候,优化器会根据分区定义过滤那些没有我们需要数据的分区,这样查询就无须扫描所有分区—只需要查询包含需要数据的分区就可以了。

理解分区时可以将其当作索引的最初形态,以代价非常小的方式定位到需要的数据在哪一片“区域”。

优点

(1)查询优化:分区最大的优点是在执行查询的时候,优化器会根据分区定义过滤那些没有我们需要数据的分区,可以让查询扫描更少的数据(在某些情况)所以对于访问分区表来说,很重要的一点就是要在WHERE条件中带入分区列,有时候即使看似多余也要带上,这样就可以让优化器能过过滤掉无须访问的分区。如果没有这些条件,就会访问所有分区。

注意:MySQL只能在使用分区函数的列本身进行比较时才能过滤分区,而不能根据表达式的值去过滤分区,即使这个表达式就是分区函数也不行。这就和查询中使用独立的列才能使用索引的道理一样。

(2)分区表的数据更容易维护。例如想批量删除大量数据可以使用清除整个分区的方式。另外,还可以对一个独立分区进行优化、检查、修复等操作。

(3)分区表的数据可以分布在不同的物理设备上,从而高效地利用多个硬件设备

(4)可以使用分区表来避免某些特殊的瓶颈,例如InnoDB的单个索引的互斥访问,ext3文件系统的inode锁竞争等。

(5)如果需要,还可以备份和恢复独立的分区,这在非常大的数据集的场景下效果非常好。

使用场景

表非常大以至无法全部都放在内存中,或者只在表的最后部分有热点数据,其他都是历史数据。Eg:假设我们希望从一个非常大的表中查询出一段时间的记录(好比查询10亿条记录的表中最近几个月的数据),而这个表中包含了很多年的历史数据,数据是按照时间排序的。因为数据量巨大,肯定不能在每次查询的时候都扫描全表。考虑到索引在空间和维护上的消耗,也不希望使用索引。

注意:当数据量超大的时候,B-Tree索引就无法起作用了。除非是索引覆盖查询,否则数据库服务器需要根据索引扫描的结果回表,查询所有符合条件的记录,如果数据量巨大,这将产生大量随机I/O,随之,数据库的响应时间将大到不可接受的程度。另外,索引维护(磁盘空间、I/O操作)的代价也非常高。

重要限制

(1)一个表最多只能有1024个分区。

(2)在MySQL5.1中分区表达式必须是整数,或者是返回整数的表达式,MySQL5.5之后,可以直接使用列(RANGE COLUMNS类型)来进行分区,这样即使是基于时间的分区也无需再将其转成一个整数。

(3)如果分区字段中有主键或者唯一索引列,那么所有主键列和唯一索引列都必须包含进来。(若不理解请看下面分区表使用注意事项

(4)分区表中无法使用外键约束。

原理

分区表是由多个相关的底层表实现,这些底层表也是由句柄对象表示,所以我们也可以直接访问各个分区,存储引擎管理分区的各个底层表和管理普通表一样(所有的底层表都必须使用相同的存储引擎),分区表的索引只是在各个底层表上各自加上一个相同的索引,从存储引擎的角度来看,底层表和一个普通表没有任何不同,存储引擎也无须知道这是一个普通表还是一个分区表的一部分。

在分区表上进行增删改查记录时,分区表先打开并锁住所有的底层表,MySQL先确定这条记录属于哪个分区,再对相应底层表进行操作。虽然每个操作都有“先打开并锁住所有的底层表”,但这并不是说分区表在处理过程中是锁住全表的。如果存储引擎能够自己实现行级锁,例如innoDb,则会在分区层释放对应表锁。这个加锁和解锁过程与普通InnoDB上的查询类似。

分区表使用注意事项

(1)主键中必须包含表的分区函数中的所有列

<span role="heading" aria-level="2">分区表-理论

在创建分区时如果表中存在主键,那么分区列必须是主键或包含于主键中。否则会报

<span role="heading" aria-level="2">分区表-理论

意思是主键中必须包含表的分区函数中的所有列。所以如果我们在使用创建时间作为分区列进行分区的时候,就需要将创建时间和主键id当作联合主键。

所以,要创建基于列c 的数据分片的分区表,主键必须包含列 c,比如下面的建表语句:

<span role="heading" aria-level="2">分区表-理论

 创建完表后,在物理存储上会看到四个分区所对应 ibd 文件,也就是把数据根据时间列 c 存储到对应的 4 个文件中:

<span role="heading" aria-level="2">分区表-理论

所以,你要理解的是:MySQL 中的分区表是把一张大表拆成了多张表,每张表有自己的索引,从逻辑上看是一张表,但物理上存储在不同文件中。

(2)唯一索引必须包含分区函数中所有列

 在 MySQL 数据库中,分区表的索引都是局部,而非全局。也就是说,索引在每个分区文件中都是独立的,所以分区表上的唯一索引必须包含分区列信息,否则创建会报错,比如:

<span role="heading" aria-level="2">分区表-理论

你可以看到错误提示: 唯一索引必须包含分区函数中所有列。而下面的创建才能成功:

 <span role="heading" aria-level="2">分区表-理论

但是,正因为唯一索引包含了分区列,唯一索引也就变成仅在当前分区唯一,而不是全局唯一了。那么对于上面的表 t,插入下面这两条记录都是可以的:

 <span role="heading" aria-level="2">分区表-理论

你可以看到,列 d 都是字符串‘aaa’,但依然可以插入。这样带来的影响是列 d 并不是唯一的,所以你要由当前分区唯一实现全局唯一。

那如何实现全局唯一索引呢?

 和之前表结构设计时一样,唯一索引使用全局唯一的字符串(如类似 UUID 的实现),这样就能避免局部唯一的问题。

分区表在业务上的设计

而为了让你更好理解分区表的使用,我们继续看一个真实业务的分区表设计。

以电商中的订单表 Orders 为例,如果在类似淘宝的海量互联网业务中,Orders 表的数据量会非常巨大,假设一天产生 5000 万的订单,那么一年表 Orders 就有近 180 亿的记录。

所以对于订单表,在数据库中通常只保存最近一年甚至更短时间的数据,而历史订单数据会入历史库。除非存在 1 年以上退款的订单,大部分订单一旦完成,这些数据从业务角度就没用了。

那么如果你想方便管理订单表中的数据,可以对表 Orders 按年创建分区表,如:

 <span role="heading" aria-level="2">分区表-理论

 你可以看到,这时 Orders 表的主键修改为了(o_orderkey,O_ORDERDATE),数据按照年进行分区存储。那么如果要删除 1 年前的数据,比如删除 1998 年的数据,之前需要使用下面的 SQL,比如:

 <span role="heading" aria-level="2">分区表-理论

 可这条 SQL 的执行相当慢,产生大量二进制日志,在生产系统上,也会导致数据库主从延迟的问题。而使用分区表的话,对于数据的管理就容易多了,你直接使用清空分区的命令就行:

<span role="heading" aria-level="2">分区表-理论

上述 SQL 执行速度非常快,因为实际执行过程是把分区文件删除和重建。另外产生的日志也只有一条 DDL 日志,也不会导致主从复制延迟问题

 <span role="heading" aria-level="2">分区表-理论

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/155821.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • amos路径分析结果解读_swot模型个人分析

    amos路径分析结果解读_swot模型个人分析基于Amos的路径分析与模型参数详解1数据准备1.1数据格式转换2结构方程模型建立2.1变量相互关系确定2.2路径图绘制2.3数据导入3模型运行与结果3.1模型方法参数选择3.2模型输出参数选择3.3模型运行3.4模型结果1数据准备  本文所用数据包括某地百余个土壤采样点对应的一种土壤属性含量变量(BC)及与其有关的5种环境变量(Temp,Slope,Roden,POI,GAIA),存储于“xlsx”文件内。由于本文所用的土壤采样点空间数据集并不是我的,因此

    2022年8月24日
    6
  • 软硬件版本号命名规范及原则是什么_文件版本号怎么编

    软硬件版本号命名规范及原则是什么_文件版本号怎么编1.软件版本阶段说明 Alpha版:此版本表示该软件在此阶段主要是以实现软件功能为主,通常只在软件开发者内部交流,一般而言,该版本软件的Bug较多,需要继续修改。 Beta版:该版本相对于α版已有了很大的改进,消除了严重的错误,但还是存在着一些缺陷,需要经过多次测试来进一步消除,此版本主要的修改对像是软件的UI。 RC版:该版本已经相当成熟了,基本上不存在导致错误的BUG,与即将发行的正式版相差无几。 Release版:该版本意味“最终版本”,在前面版本的一系列

    2022年9月10日
    0
  • word页数域代码

    word页数域代码针对MicrosoftWord使用alt+F9显示域代码,使用ctrl+F9插入域代码,注意:必须用ctrl+F9插入域代码,自己打括号无效第{page}页/总{numpages}页//本文档所有页数第{page}页/总{sectionpages}页//当前节所有页数…

    2022年6月9日
    104
  • larave5.6 将Excel文件数据导入数据库代码实例

    larave5.6 将Excel文件数据导入数据库代码实例

    2021年10月24日
    39
  • 在线客服系统源码 自适应手机移动端 支持多商家 带搭建教程

    在线客服系统源码 自适应手机移动端 支持多商家 带搭建教程下载链接:在线客服系统源码自适应手机移动端支持多商家支持微信公众号/微信小程序带搭建教程-PHP文档类资源-CSDN下载PHP轻量级人工在线客服系统源码自适应手机移动端支持多商家带搭建教程支持多商家支持多商家,每个注册用户为一个商家,每个商家可以添加多个客服。不限坐席每个商家可以无限添加坐席,不限制坐席数支持H5移动端系统自动适配移动端,也可以接入app(h5方式)支持微信公众号/微信小程序客服可以与微信公众号/小程序里的访客实时沟通常见问题自动回复…

    2022年7月19日
    17
  • gitlab 删除仓库_获取下拉框选中的文本值

    gitlab 删除仓库_获取下拉框选中的文本值通过git命令以及在gitlab上操作来删除gitlab上仓库的分支

    2022年10月22日
    1

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号