最佳实践 · MySQL 分区表实战指南

引言

在数据量急剧增长的今天,传统的数据库管理方式可能无法有效处理海量数据的存储和查询需求。MySQL 提供了分区表功能,这不仅能够帮助优化性能,还能简化数据管理过程。分区表允许将数据表拆分成多个逻辑上的分区,每个分区可以在物理上存储于不同的存储介质上,从而提升查询效率和数据处理速度。本文将深入探讨 MySQL 中四种主要的分区类型——范围分区(RANGE)、列表分区(LIST)、哈希分区(HASH)以及键分区(KEY),并通过实际的案例分析和示例数据,帮助你掌握如何使用这些分区技术来优化数据库性能,提升数据处理能力。

请在此添加图片描述

基础数据

为了制作一份满足上述内容的test表及数据,我们需要创建一个包含idhiredate字段的表,并插入一些示例数据。以下是具体的步骤:

创建表

CREATE TABLE test (
    id INT,
    hiredate DATETIME
);

插入数据

为了模拟大量数据,我们可以插入一些示例数据。以下是插入100万条数据的示例:

DELIMITER //

CREATE PROCEDURE InsertTestData()
BEGIN
    DECLARE i INT DEFAULT 1;
    WHILE i <= 1000000 DO
        INSERT INTO test (id, hiredate) VALUES (i, NOW() - INTERVAL FLOOR(RAND() * 3650) DAY);
        SET i = i + 1;
    END WHILE;
END //

DELIMITER ;

CALL InsertTestData();

这个存储过程会插入100万条数据,每条数据的hiredate字段是一个随机日期,范围从当前日期往前推10年。

RANGE 分区

概述

RANGE 分区基于列值的连续区间将数据分配到不同的分区。这种分区类型特别适用于时间或日期字段,可以有效地管理和清理历史数据。

请在此添加图片描述

工作原理

RANGE 分区依据列值的范围来决定记录所属的分区。例如,可以根据日期字段的值,将数据按月、按季度或按年分配到不同的分区中。这样一来,查询和删除某一时间段的数据时,只需操作相关的分区,从而提高性能和减少锁竞争。

假设有一个员工表,我们希望根据雇佣日期对数据进行分区,以便高效清理过期数据:

CREATE TABLE my_range_datetime (
    id INT,
    hiredate DATETIME
)
PARTITION BY RANGE (TO_DAYS(hiredate)) (
    PARTITION p1 VALUES LESS THAN (TO_DAYS('2017-12-02')),
    PARTITION p2 VALUES LESS THAN (TO_DAYS('2017-12-03')),
    PARTITION p3 VALUES LESS THAN (TO_DAYS('2017-12-04')),
    PARTITION p4 VALUES LESS THAN (TO_DAYS('2017-12-05')),
    PARTITION p5 VALUES LESS THAN (TO_DAYS('2017-12-06')),
    PARTITION p6 VALUES LESS THAN (TO_DAYS('2017-12-07')),
    PARTITION p7 VALUES LESS THAN (TO_DAYS('2017-12-08')),
    PARTITION p8 VALUES LESS THAN (TO_DAYS('2017-12-09')),
    PARTITION p9 VALUES LESS THAN (TO_DAYS('2017-12-10')),
    PARTITION p10 VALUES LESS THAN (TO_DAYS('2017-12-11')),
    PARTITION p11 VALUES LESS THAN (MAXVALUE)
);

在上面的示例中,p11 是一个默认分区,用于存储所有大于指定日期的记录。TO_DAYS() 函数将日期转换为天数,从而实现分区。

mysql> insert into my_range_datetime select * from test;
Query OK, 7240 rows affected
Records: 7240  Duplicates: 0  Warnings: 0

mysql> explain 
select * from my_range_datetime where hiredate >= '2017-12-07 12:45:03' and hiredate<='2017-12-10 11:12:30'; 
+----+-------------+-------------------+--------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table             | partitions   | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------------------+--------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | my_range_datetime | p7,p8,p9,p10 | ALL  | NULL          | NULL | NULL    | NULL |   11 |    11.11 | Using where |
+----+-------------+-------------------+--------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set

请注意执行计划中partitions部分的内容,仅查询了p7、p8、p9和p10这四个分区。由此可见,使用to_days函数确实能够实现分区裁剪。

上述示例是基于datetime类型的,那么对于timestamp类型,我们是否也会遇到类似的问题呢?

接下来,我们将测试一下基于UNIX_TIMESTAMP函数的RANGE分区方案,以验证其是否能够实现分区裁剪。

针对TIMESTAMP类型的分区方案

注意:对于 TIMESTAMP 类型字段,使用 UNIX_TIMESTAMP 函数来实现类似的分区:

CREATE TABLE my_range_timestamp (
    id INT,
    hiredate TIMESTAMP
)
PARTITION BY RANGE (UNIX_TIMESTAMP(hiredate)) (
    PARTITION p1 VALUES LESS THAN (UNIX_TIMESTAMP('2017-12-02 00:00:00')),
    PARTITION p2 VALUES LESS THAN (UNIX_TIMESTAMP('2017-12-03 00:00:00')),
    PARTITION p3 VALUES LESS THAN (UNIX_TIMESTAMP('2017-12-04 00:00:00')),
    PARTITION p4 VALUES LESS THAN (UNIX_TIMESTAMP('2017-12-05 00:00:00')),
    PARTITION p5 VALUES LESS THAN (UNIX_TIMESTAMP('2017-12-06 00:00:00')),
    PARTITION p6 VALUES LESS THAN (UNIX_TIMESTAMP('2017-12-07 00:00:00')),
    PARTITION p7 VALUES LESS THAN (UNIX_TIMESTAMP('2017-12-08 00:00:00')),
    PARTITION p8 VALUES LESS THAN (UNIX_TIMESTAMP('2017-12-09 00:00:00')),
    PARTITION p9 VALUES LESS THAN (UNIX_TIMESTAMP('2017-12-10 00:00:00')),
    PARTITION p10 VALUES LESS THAN (UNIX_TIMESTAMP('2017-12-11 00:00:00')),
    PARTITION p11 VALUES LESS THAN (MAXVALUE) 
);

请在此添加图片描述

同样地,该方案也能实现分区裁剪。

在MySQL 5.7版本之前,针对DATE和DATETIME类型的列,要实现分区裁剪,我们只能依赖于YEAR()和TO_DAYS()函数。然而,在MySQL 5.7版本中,引入了一个新的函数——TO_SECONDS(),为分区裁剪提供了更多的选择。

LIST 分区

概述

LIST 分区用于将数据分配到不同的分区,依据的是离散的枚举值列表。与 RANGE 分区不同,LIST 分区适合处理那些不连续的值,例如状态码、地区码等。

工作原理

LIST 分区通过枚举所有可能的值,并将它们映射到特定的分区中。这样,在插入数据时,系统可以根据列值快速确定数据应放置在哪个分区。

如果我们有一个表保存订单的状态信息,可以使用 LIST 分区来高效地管理不同状态的订单:

CREATE TABLE orders (
    id INT,
    status INT
)
PARTITION BY LIST (status) (
    PARTITION p0 VALUES IN (0, 1, 2),    -- 代表未处理和处理中状态
    PARTITION p1 VALUES IN (3, 4, 5)     -- 代表已完成和已取消状态
);

注意:LIST 分区列最好是非 NULL 列,否则在插入数据时可能会出现错误。

HASH 分区

概述

HASH 分区通过对指定列的哈希值进行分区,适用于没有明确分区字段的数据表。HASH 分区确保数据均匀分布在各个分区中。

工作原理

HASH 分区对指定列的值进行哈希计算,然后根据计算结果将数据分配到不同的分区。由于哈希函数的性质,这种分区方式可以较好地实现数据均匀分布。

对于没有明显分区字段的用户表,可以使用 HASH 分区:

CREATE TABLE users (
    id INT NOT NULL,
    name VARCHAR(50),
    registration_date DATE
)
PARTITION BY HASH(id)
PARTITIONS 4;

在这个例子中,数据根据 id 列的哈希值分配到 4 个分区中。

LINEAR HASH 分区

概述

LINEAR HASH 分区是 HASH 分区的一种变体,通过线性哈希算法来进行分区。它适合大数据量的场景,例如 TB 级的数据表。

工作原理

与传统的 HASH 分区不同,LINEAR HASH 分区使用线性哈希算法进行分区,这可以使得在数据增长时,增加、删除、合并和拆分分区的操作更为高效。然而,这也可能导致数据分布不均匀的情况。

对于大规模的数据表,使用 LINEAR HASH 分区可以优化分区操作:

CREATE TABLE large_table (
    id INT NOT NULL,
    data VARCHAR(100)
)
PARTITION BY LINEAR HASH(id)
PARTITIONS 4;

KEY 分区

概述

KEY 分区与 HASH 分区类似,但允许使用多个列作为分区键,并基于列的 MD5 值进行分区。适用于分区键需要多个列的情况。

工作原理

KEY 分区通过计算列值的 MD5 值并对其进行分区,可以将数据均匀地分配到不同的分区中。它支持对多个列进行分区,但要求列值必须是整数或可以转换为整数的类型。

如果我们希望将数据按多个列的值进行分区,可以使用 KEY 分区:

CREATE TABLE multi_key_table (
    id INT NOT NULL PRIMARY KEY,
    name VARCHAR(50),
    category INT
)
PARTITION BY KEY (id, category)
PARTITIONS 4;

如果表中有主键或唯一键,KEY 分区默认使用这些键进行分区。如果没有,则需要显式指定分区列。

小结

  • RANGE 分区适用于具有连续区间的字段,如日期或时间,可以显著提高数据管理效率。
  • LIST 分区适用于离散值的场景,如状态码或地区码,适合处理特定的枚举值。
  • HASH 分区适用于没有明显分区特征的数据表,确保数据均匀分布。
  • LINEAR HASH 分区在大数据量场景下优化分区操作,但可能导致数据分布不均。
  • KEY 分区允许使用多个列作为分区键,基于列的 MD5 值进行分区,适合复杂的分区需求。

每种分区类型的选择应根据数据特征和应用需求来决定,以实现最佳的性能和管理效果。

结尾

通过对 MySQL 分区表的了解,我们可以看到,合理利用分区技术能够显著提升数据管理的效率和查询性能。无论是需要按照时间段清理历史数据,还是希望将数据分散到多个分区以加快检索速度,MySQL 的分区机制都能为复杂的数据场景提供有效的解决方案。在实际应用中,选择合适的分区类型并根据业务需求调整分区策略,将帮助我们在面对海量数据时保持系统的高效稳定。希望本文提供的实用示例和最佳实践,能够为数据库管理的道路上提供价值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/876221.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

资源管理新视角:利用 FastAPI Lifespan 事件优化你的应用II

本文说明在 FastAPI 应用程序中使用 lifespan 事件来管理资源的加载和卸载。lifespan 事件允许你在应用启动时执行一些初始化代码&#xff0c;并在应用关闭时执行一些清理代码。这是通过使用异步上下文管理器实现的&#xff0c;具体来说&#xff0c;是通过 asynccontextmanager…

什么是职场?职场的本质又是什么呢?

最近&#xff0c;经常看到很多职场相关的&#xff0c;比如职场必备技能、职场人际关系、职场晋升等等&#xff0c;这些都是职场的一些方面&#xff0c;但是却少有人来深入剖析什么是职场&#xff0c;职场的本质又是什么&#xff0c;今天我们就来一起来聊一聊&#xff0c;到底职…

音视频入门基础:AAC专题(5)——FFmpeg源码中,判断某文件是否为AAC裸流文件的实现

一、引言 通过FFmpeg命令&#xff1a; ./ffmpeg -i XXX.aac 可以判断出某个文件是否为AAC裸流文件&#xff1a; 所以FFmpeg是怎样判断出某个文件是否为AAC裸流文件呢&#xff1f;它内部其实是通过adts_aac_probe函数来判断的。从《FFmpeg源码&#xff1a;av_probe_input_for…

性能测试的复习3-jmeter的断言、参数化、提取器

一、断言、参数化、提取器 需求&#xff1a; 提取查天气获取城市名请求的响应结果&#xff1a;城市对查天气获取城市名的响应结果进行响应断言和json断言对查天气获取城市名添加用户参数 1、步骤 查看天气获取城市名 json提取器&#xff08;对响应结果提取、另一个接口请求…

也许你该了解下,DeepSeek Coder这个国产目前最牛逼的编码大模型,或许你真的用得上

你是不是也有这样的困惑:代码写不出来、调不通、效率低下,明明花了几个小时,结果却一无所获?别担心,不光是你,我也曾经有过同样的苦恼。但今天我要和你聊的,是一个能够改变这种局面的新工具——DeepSeek Coder。这个工具有多厉害?它能帮你解决闭源代码难以获取的问题,…

复杂情感识别系统

复杂情感识别系统&#xff08;CERS&#xff09;是一种先进的技术平台&#xff0c;旨在通过分析情感的组合、相互关系及其动态变化来解读和识别复杂的情感状态。这种系统通常采用以下技术和方法&#xff1a; 机器学习与深度学习&#xff1a; 通过训练算法识别和解释大量情感数据…

Blender/3ds Max/C4D哪个软件好?

在3D建模和动画制作领域&#xff0c;Blender、3ds Max和Cinema 4D&#xff08;C4D&#xff09;都是备受赞誉的软件。每个软件都有其独特的优势和特点&#xff0c;选择哪个软件取决于用户的具体需求和个人偏好。今天&#xff0c;成都渲染101云渲染就来分析一些这三款软件的情况&…

Linux服务器配合Xshell+Tensorboard实现深度学习训练过程可视化

问题背景&#xff1a; 在深度学习领域&#xff0c;监控模型的训练过程是非常重要的。TensorBoard 是 TensorFlow 提供的一个可视化工具&#xff0c;可以帮助我们直观地理解模型的训练和验证过程。我们一般在 Windows 系统只需要在自己的浏览器输入localhost:6006就可以观察训练…

Java的发展史与前景

&#x1f308;个人主页&#xff1a;Yui_ &#x1f308;Linux专栏&#xff1a;Linux &#x1f308;C语言笔记专栏&#xff1a;C语言笔记 &#x1f308;数据结构专栏&#xff1a;数据结构 &#x1f308;C专栏&#xff1a;C 文章目录 0. Java语言的发展史1.概述1.1 什么是Java1.2 …

java项目之基于工程教育认证的计算机课程管理平台(源码+论文)

项目简介 基于工程教育认证的计算机课程管理平台的主要管理员可以管理教师&#xff0c;可以对教师信息修改删除以及查询操作&#xff1b;可以对通知公告信息进行添加&#xff0c;修改&#xff0c;删除以及查询操作&#xff1b;可以对学生信息进行添加&#xff0c;修改&#xf…

Oracle绑定变量窥视与自适应游标共享

一.Oracle的绑定变量窥视与自适应游标共享 创建test表&#xff0c;列status存在2个值&#xff0c;有数据倾斜&#xff0c;在列status create table test as select rownum id,DBMS_RANDOM.STRING(A,12) name,DECODE(MOD(ROWNUM,500),0,Inactive,Active) status from all_obj…

Rust Windows下编译 静态链接VCRuntime140.dll

Rust 编译出来的exe默认动态链接VC运行库&#xff0c;分发电脑上需要安装有Microsoft Visual C Redistributable for Visual Studio 2015运行库。 编译时能静态链接进去&#xff0c;就省去客户端未安装运行库的问题。方法如下: 只需在当前根目录下新建.cargo\config.toml&#…

【西电电装实习】6. 手装无人机的蓝牙断连debug

文章目录 前言零、闪灯状态零零、翻滚角&#xff0c;俯仰角&#xff0c;偏航角一、问题描述二、现象解释三、解决方案参考文献 前言 在 西电无人机电装实习 时遇到的问题使用蓝牙芯片 CH582F。沁恒的蓝牙芯片CH582F是一款集成了BLE&#xff08;Bluetooth Low Energy&#xff0…

windows安装docker、elasticsearch、kibana、cerebro、logstash

文章目录 1. 安装docker1.1. 两大要点1.1.1. 安装启用hyper-v电脑不存在hyper-v的情况 1.1.2. 下载安装docker 2. 在docker里面安装elasticSearch&#xff0c;kibana&#xff0c;cerebro3. 安装logstash-将数据导入到elasticSearch3.1 安装logstash3.1.1 注意事项3.1.1.1. 等了…

[数据集][目标检测]高铁受电弓检测数据集VOC+YOLO格式1245张2类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;1245 标注数量(xml文件个数)&#xff1a;1245 标注数量(txt文件个数)&#xff1a;1245 标注…

OrionX vGPU 研发测试场景下最佳实践之Jupyter模式

在上周的文章中&#xff0c;我们讲述了OrionX vGPU研发测试场景下最佳实践之SSH模式&#xff0c;今天&#xff0c;让我们走进 Jupyter模式下的最佳实践。 • Jupyter模式&#xff1a;Jupyter是最近几年算法人员使用比较多的一种工具&#xff0c;很多企业已经将其改造集成开发工…

MongoDB根据字段内容长度查询语句

db.getCollection("qlzx_penalties_business_raw").find({$expr: {$lt: [{ $strLenCP: "$punish_name" }, 5]},"punish_name_type" : "机构", "source_data" : /中国/,})解释&#xff1a; 1-"source_data" : /中…

召回02 Swing 召回通道

为了避免小圈子重合却误判物品相似度很高&#xff1a;降低小圈子对相似度的影响。

Element-ui el-table 全局表格排序

实现效果如下&#xff1a; 一、当页数据排序 如果只想要当前页面排序&#xff0c;只会涉及到前端&#xff0c;只需在<el-table-column>标签上添加 :sortable"true"即可 二、自定义排序 如果想要全局排序&#xff0c;需要自定义排序函数&#xff0c;请求后台排…

Unity Timeline

数据存储 TimeLine和Animation一样也是资源&#xff0c;以.playable的格式存储&#xff0c;可以通过Playable Director进行加载播放。 Playable具有以下优势&#xff1a; 结构简单&#xff1b; 运行时创建、添加和删除&#xff1b; 更加灵活&#xff0c;可以直接控制动画的各种…