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

news2024/11/17 21:41:55

引言

在数据量急剧增长的今天,传统的数据库管理方式可能无法有效处理海量数据的存储和查询需求。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.coloradmin.cn/o/2136751.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【特点】浅谈大模型的特点

在人工智能(AI)的发展历程中&#xff0c;大模型无疑是一个重要的里程碑。大模型是指利用海量数据&#xff0c;通过先进的算法和技术&#xff0c;训练得到的具有强大预测和决策能力的模型&#xff0c;这类模型具备了强大的语言理解和生成能力&#xff0c;能够完成各种复杂的自然…

【近源攻击】badusb制作

❤️博客主页&#xff1a; iknow181 &#x1f525;系列专栏&#xff1a; 网络安全、 Python、JavaSE、JavaWeb、CCNP &#x1f389;欢迎大家点赞&#x1f44d;收藏⭐评论✍ 在这篇博客中&#xff0c;我将详细介绍如何从零开始使用 ATtiny85 开发板制作一个 BadUSB。通过这个教程…

如何管理付费媒体预算:分配、风险与扩展

对于优先考虑利润率和现金流的企业而言&#xff0c;管理广告预算是一项基本技能。由于人为错误导致的超支几乎总是意味着与客户和利益相关者的艰难对话。这时候&#xff0c;借助光年AI智能平台可以极大程度地降低这种风险&#xff0c;通过AI驱动的全面流量和增长服务&#xff0…

拥塞控制算法为何失效,网络为何难以测量?

紧接着上文 如何测量一个(传输网络)系统的容量 给出的方法&#xff0c;看一下如何测量网络容量&#xff0c;如果真的能测量网络容量&#xff0c;传输算法就好设计了。 先给出答案&#xff0c;很遗憾&#xff0c;根本无法测量&#xff0c;请阅读 why we don’t know how to sim…

前端-CDN的理解及CDN一些使用平台

目录 1.CDN的概念 &#xff08;1&#xff09; 分发服务系统 &#xff08;2&#xff09;均衡负荷系统 &#xff08;3&#xff09;运营管理系统 &#xff08;4&#xff09;缓存系统 &#xff08;5&#xff09;支撑系统 2.CDN的基本工作原理 3.CDN使用缓存资源过程 4.CDN…

CesiumJS+SuperMap3D.js混用实现天际线分析

版本简介&#xff1a; cesium&#xff1a;1.99&#xff1b;Supermap3D&#xff1a;SuperMap iClient JavaScript 11i(2023)&#xff1b; 官方下载文档链家&#xff1a;SuperMap技术资源中心|为您提供全面的在线技术服务 示例参考&#xff1a;support.supermap.com.cn:8090/w…

【Arduino】BNO085 姿态的 3D模型 展示方法(映射到 Unity)

总览 1.arduino 代码和库等… 2.Unity 的部分&#xff0c;创建一个 3D 工程&#xff0c;然后创建一个 cube&#xff0c;绑定一个脚本文件 3.效果预览&#xff1a; 【Arduino】BNO085 姿态的 3D模型 展示方法&#xff08;映射到 Unity&#xff09; 一、Arduino 部分 1.使用的…

《Exploit temporal cues in multi-camera 3D object detection》论文泛读

ReadPaperhttps://readpaper.com/pdf-annotate/note?pdfId4666749915775385601eId2491528568128599808 针对单帧数据含有的信息太少的问题&#xff0c;提出了一种新的方法&#xff0c;BEVDet4D&#xff0c;这种方法可以访问时间线索&#xff0c;并且取得了较好的表现&#xff…

C++类与对象深度解析(一):从抽象到实践的全面入门指南

文章目录 C 类与对象——详细入门指南前言1. 类的定义1.1 类定义的基本格式示例代码解释 1.2 访问限定符示例代码解释 1.3 类域示例代码解释 1.4 成员命名规范常见的命名约定&#xff1a;示例&#xff1a;拓展&#xff1a; 1.5 class与struct的默认访问权限示例&#xff1a; 2.…

Leetcode 每日一题:Decode String

写在前面&#xff1a; 最近求职季找工作忙的焦头烂额&#xff0c;同时这个学期的助教工作也比之前的工时多了一倍&#xff0c;昨天又拖更了真的对不起大家&#xff5e;&#xff5e; 今天我们来看一道稍微轻松一点的题&#xff0c;这道题目来源于 Valid Parenthesis&#xff0…

房产销售系统:SpringBoot技术优化方案

第三章 系统分析 3.1 系统设计目标 房产销售系统主要是为了用户方便对房源信息管理、房源类型管理、房子户型管理、交易订单管理、预约看房管理、评价管理等信息进行查询&#xff0c;也是为了更好的让管理员进行更好存储所有数据信息及快速方便的检索功能&#xff0c;对系统的各…

ESP32聊天机器人之一

想做情感陪伴机器人&#xff0c;看到B站有个项目很有趣&#xff0c;使用一块esp32复刻了B站MeteWu的ESP32大模型聊天项目。 自己做了一些修改&#xff0c;加了一些简单的表情&#xff0c;角色扮演&#xff0c;切换大模型和温湿度传感器等功能。可以用于玩具&#xff0c;聊天机…

第307题|快速掌握 反常积分敛散性判定的方法|武忠祥老师每日一题

解题思路&#xff1a;先判断这个反常积分的敛散性&#xff0c;再讨论a的取值范围; 判断反常积分的敛散性&#xff0c;我们通常有三个方法&#xff1a; &#xff08;1&#xff09;根据定义&#xff0c;通常在原函数比较好求的情况下&#xff0c;可以根据定义 &#xff08;2&am…

IDEA 常用配置和开发插件

件市场中搜索并安装“Git Integration”插件。 一、前言 在本篇文章中我会为大家总结一些我自己常用的配置和开发插件&#xff0c;此外也给大家提供一个建议&#xff0c;可以根据自己的项目需求和个人偏好选择适合的插件。另外&#xff0c;IDEA 也在不断更新&#xff0c;可能会…

『功能项目』战士职业平A怪物掉血【44】

我们打开上一篇43事件中心的项目&#xff0c; 本章要做的事情是给主角增加一个xxxCtrl.cs脚本&#xff0c;再创建一个xxxOpt.cs调用xxxCtrl.cs机制层利用事件中心再写一个主角战士平A对怪物的伤害 首先创建脚本&#xff1a;PlayerCtrl.cs using UnityEngine; public class Pla…

2024年微电子与纳米技术国际研讨会(ICMN 2024) Microelectronics and Nanotechnology

文章目录 一、会议详情二、重要信息三、大会介绍四、出席嘉宾五、征稿主题六、咨询 一、会议详情 二、重要信息 大会官网&#xff1a;https://ais.cn/u/vEbMBz提交检索&#xff1a;EI Compendex、IEEE Xplore、Scopus大会时间&#xff1a;2024年9月20-22日地点&#xff1a;成都…

Java项目: 基于SpringBoot+mybatis+maven服装生产管理系统(含源码+数据库+任务书+开题报告+毕业论文)

一、项目简介 本项目是一套基于SpringBootmybatismaven服装生产管理系统 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观、操作简…

0基础跟德姆(dom)一起学AI 数据处理和统计分析02-Linux进阶

* vi编辑器 * 权限相关 * 进程,网络相关 * 压缩和解压缩 * 软件安装-yum方式 * 其它命令 --- 1.过滤和管道命令 shell # grep命令, 用来过滤的 # 格式 grep [-n] 关键字 文件路径 # 从文件中过滤出要查找的内容, -n:表示带行号. # | 管道符, 即: 把前边命令的执行结果,…

Ceisum(SuperMap iClient3D for Cesium)实现平面裁剪

1&#xff1a;参考API文档&#xff1a;SuperMap iClient3D for Cesium 开发指南 2&#xff1a;官网示例&#xff1a;support.supermap.com.cn:8090/webgl/Cesium/examples/webgl/examples.html#layer 3&#xff1a;SuperMap iServer&#xff1a;欢迎使用 SuperMap iServer 11…

ArcGIS属性表汉字转拼音

直接复制粘贴现成代码&#xff1a; # -*- coding: utf-8 -*-import arcpyfrom arcpy import envimport osimport pypinyin import sys# 不带声调皿stylepypinyin.NORMAL)def pinyin(word): s for i in pypinyin.pinyin(word, stylepypinyin.NORMAL): s .join(…