前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >第42期:MySQL 是否有必要多列分区

第42期:MySQL 是否有必要多列分区

原创
作者头像
爱可生开源社区
发布于 2022-06-29 08:15:02
发布于 2022-06-29 08:15:02
1.8K0
举报

之前的篇章我们讨论的都是基于单列的分区表,那有无必要建立基于多列的分区表?这种分区表数据分布是否均匀?有无特殊的应用场景?有无特殊的优化策略?本篇基于这些问题来进行重点解读。

MySQL 不仅支持基于单列分区,也支持基于多列分区。比如基于字段(f1,f2,f3)来建立分区表,使用方法和使用场景都有些类似于联合索引。比如下面查询语句,同时对列(f1,f2,f3) 进行过滤。

代码语言:sql
AI代码解释
复制
select * from p1 where f1 = 2 and f2 = 2 and f3 = 2;

多列分区表的前提是参与分区的列检索频率均等,如果不均等,就没有必要使用多列分区。

我们还是以具体实例来验证下多列分区的优缺点以及适用场景,这样理解起来更加透彻。

建立一张表p1,字段r1,r2,r3分别取值为1-8,1-5,1-5.

代码语言:sql
AI代码解释
复制
create table p1(r1 int,r2 int,r3 int,log_date datetime);

按照字段(r1,r2,r3) 的分布范围,我来写个存储过程处理下表p1,变为分区表。存储过程代码如下:

代码语言:sql
AI代码解释
复制
DELIMITER $$

USE `ytt_new`$$

DROP PROCEDURE IF EXISTS `sp_add_partition_ytt_new_p1`$$

CREATE DEFINER=`root`@`%` PROCEDURE `sp_add_partition_ytt_new_p1`()
BEGIN
	DECLARE i,j,k INT UNSIGNED DEFAULT 1;
	SET @stmt = '';
	SET @stmt_begin = 'ALTER TABLE p1 PARTITION BY RANGE COLUMNS (r1,r2,r3)(';
        WHILE i <= 8 DO
	   set j = 1;
	   while j <= 5 do
	     set k = 1;
	     while k <= 5 do
               SET @stmt = CONCAT(@stmt,' PARTITION p',i,j,k,' VALUES LESS THAN (',i,',',j,',',k,'),');
               set k = k + 1;
	     end while;
	     set j = j + 1;
	   end while;
	   SET i = i + 1;        
        END WHILE;	
	SET @stmt_end = 'PARTITION p_max VALUES LESS THAN (maxvalue,maxvalue,maxvalue))';
        SET @stmt = CONCAT(@stmt_begin,@stmt,@stmt_end);
        PREPARE s1 FROM @stmt;
        EXECUTE s1;
        DROP PREPARE s1;
        SET @stmt = NULL;
        SET @stmt_begin = NULL;
        SET @stmt_end = NULL;	
	END$$

DELIMITER ;

调用存储过程,变更表p1为多列分区表,此时表p1有201个分区,记录数为500W条。

代码语言:sql
AI代码解释
复制
mysql> call sp_add_partition_ytt_new_p1;
Query OK, 0 rows affected (14.89 sec)

mysql> select count(partition_name) as partition_count  from information_schema.partitions where table_schema = 'ytt_new' and table_name ='p1';
+-----------------+
| partition_count |
+-----------------+
|             201 |
+-----------------+
1 row in set (0.00 sec)

mysql> select count(*) from p1;
+----------+
| count(*) |
+----------+
|  5000000 |
+----------+
1 row in set (12.01 sec)

用同样的方法建立一张分区表p2,来对单列分区表与多列分区表在一些场景下的性能做下对比:

分区表p2按照字段r1分区,仅仅分了9个。

代码语言:sql
AI代码解释
复制
mysql> CREATE TABLE `p2` (
  `r1` int DEFAULT NULL,
  `r2` int DEFAULT NULL,
  `r3` int DEFAULT NULL,
  `log_date` datetime DEFAULT NULL
) ENGINE=InnoDB
PARTITION BY RANGE  COLUMNS(r1)
(PARTITION p1 VALUES LESS THAN (1) ,
 PARTITION p2 VALUES LESS THAN (2) ,
 PARTITION p3 VALUES LESS THAN (3) ,
 PARTITION p4 VALUES LESS THAN (4) ,
 PARTITION p5 VALUES LESS THAN (5) ,
 PARTITION p6 VALUES LESS THAN (6) ,
 PARTITION p7 VALUES LESS THAN (7) ,
 PARTITION p8 VALUES LESS THAN (8) ,
 PARTITION p_max VALUES LESS THAN (MAXVALUE) 
)
1 row in set (0.00 sec)

mysql> insert into p2 select * from p1;
Query OK, 5000000 rows affected (1 min 37.92 sec)
Records: 5000000  Duplicates: 0  Warnings: 0

多个字段等值过滤的性能对比:同样的查询条件,表p1(执行时间0.02秒)比p2(执行时间0.49秒)要快几十倍。

代码语言:sql
AI代码解释
复制
mysql> select count(*) from p1 where r1 = 2 and r2 = 2 and r3 = 2;
+----------+
| count(*) |
+----------+
|    24992 |
+----------+
1 row in set (0.02 sec)

mysql> select count(*) from p2 where r1 = 2 and r2 = 2 and r3 = 2;
+----------+
| count(*) |
+----------+
|    24992 |
+----------+
1 row in set (0.49 sec)

查看两者执行计划对比: 同样的查询,表p1扫描行数只有2W多,而表p2扫描行数有62W行,相差巨大。

代码语言:sql
AI代码解释
复制
mysql> explain select count(*) from p1 where r1 = 2 and r2 = 2 and r3 = 2\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: p1
   partitions: p223
         type: ALL
...
         rows: 24711
     filtered: 0.10
        Extra: Using where
1 row in set, 1 warning (0.00 sec)

mysql> explain select count(*) from p2 where r1 = 2 and r2 = 2 and r3 = 2\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: p2
   partitions: p3
         type: ALL
...
         rows: 623239
     filtered: 0.10
        Extra: Using where
1 row in set, 1 warning (0.00 sec)

如果过滤字段不完整呢?比如不检索最后一列,再次做下对比:同样表p1(0.1秒)比表p2(0.52秒)执行时间要少几倍。

代码语言:sql
AI代码解释
复制
mysql> select count(*) from p1 where r1 = 2 and r2 = 2;
+----------+
| count(*) |
+----------+
|   124649 |
+----------+
1 row in set (0.10 sec)

mysql> select count(*) from p2 where r1 = 2 and r2 = 2;
+----------+
| count(*) |
+----------+
|   124649 |
+----------+
1 row in set (0.52 sec)

那只检索第一列呢:这次表p1和p2执行时间上差不多,p2稍微占优势。

代码语言:sql
AI代码解释
复制
mysql> select count(*) from p1 where r1 = 2 ;
+----------+
| count(*) |
+----------+
|   624599 |
+----------+
1 row in set (0.56 sec)

mysql> select count(*) from p2 where r1 = 2 ;
+----------+
| count(*) |
+----------+
|   624599 |
+----------+
1 row in set (0.45 sec)

看下执行计划对比:表p1扫描的分区数为26个,表p2仅扫描1个分区,分区数量上表p2相对少很多。

代码语言:sql
AI代码解释
复制
mysql> explain select count(*) from p1 where r1 = 2 \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: p1
   partitions: p211,p212,p213,p214,p215,p221,p222,p223,p224,p225,p231,p232,p233,p234,p235,p241,p242,p243,p244,p245,p251,p252,p253,p254,p255,p311
         type: ALL
...
         rows: 648074
     filtered: 10.00
        Extra: Using where
1 row in set, 1 warning (0.00 sec)

mysql> explain select count(*) from p2 where r1 = 2 \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: p2
   partitions: p3
         type: ALL
...
         rows: 623239
     filtered: 10.00
        Extra: Using where
1 row in set, 1 warning (0.00 sec)

如果把字段r1拿掉呢?执行时间也相差无几,表p1和表p2都会扫描所有分区。

代码语言:sql
AI代码解释
复制
mysql> select count(*) from p1 where  r2 = 2;
+----------+
| count(*) |
+----------+
|   998700 |
+----------+
1 row in set (3.87 sec)

mysql> select count(*) from p2 where  r2 = 2;
+----------+
| count(*) |
+----------+
|   998700 |
+----------+
1 row in set (3.75 sec)

那鉴于此,再来探讨一个问题:对于多列分区,字段的排列顺序是否重要?

关于这个顺序要和我们查询语句对应的过滤条件来一一说明。 类似下面两类 SQL :

代码语言:sql
AI代码解释
复制
SQL 1select * from p1 where r1 = 2 and r2 = 2 and r3 = 2;

对于SQL 1,顺序无关紧要,因为三个列在查询时都已包含;

代码语言:sql
AI代码解释
复制
SQL 2: select * from p1 where r1 = 2 and r2 = 2;

对于SQL 2 , (r1,r2,r3) 和 (r2,r1,r3) 都可以满足。

代码语言:sql
AI代码解释
复制
SQL 3select * from p1 where r2 = 2 and r3 = 2;

对于SQL 3, (r2,r3,r1) 和 (r3,r2,r1) 也都可以满足。

用同样的方法来建立分区表p3,分区字段顺序为(r2,r3,r1):

代码语言:sql
AI代码解释
复制
mysql> show create table p3\G
*************************** 1. row ***************************
       Table: p3
Create Table: CREATE TABLE `p3` (
  `r1` int DEFAULT NULL,
  `r2` int DEFAULT NULL,
  `r3` int DEFAULT NULL,
  `log_date` datetime DEFAULT NULL
) ENGINE=InnoDB 
/*!50500 PARTITION BY RANGE  COLUMNS(r2,r3,r1)
(PARTITION p111 VALUES LESS THAN (1,1,1) ENGINE = InnoDB,
...

对于表p3来讲:下面这条 SQL 执行时间比表p1要快几十倍,由于分区字段顺序不同,表p1要扫描所有分区才能出结果。

代码语言:sql
AI代码解释
复制
mysql> select count(*) from p3 where r2 = 1 and r3 = 4 ;
+----------+
| count(*) |
+----------+
|   199648 |
+----------+
1 row in set (0.22 sec)

mysql> select count(*) from p1 where r2 = 1 and r3 = 4 ;
+----------+
| count(*) |
+----------+
|   199648 |
+----------+
1 row in set (5.05 sec)

所以对于多列分区表,正如开头讲的一样,它和联合索引的使用方法、注意事项、使用场景也都很类似。对于某些特定的场景,使用多列分区能显著加快查询性能。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
1 条评论
热度
最新
很详细,感谢分享
很详细,感谢分享
回复回复点赞举报
推荐阅读
掌握后可为孩子收藏的MySQL入门全套
数据库(Database)是按照数据结构来组织、存储和管理数据的仓库,它产生于距今六十多年前,随着信息技术和市场的发展,特别是二十世纪九十年代以后,数据管理不再仅仅是存储和管理数据,而转变成用户所需要的各种数据管理的方式。数据库有很多种类型,从最简单的存储有各种数据的表格到能够进行海量数据存储的大型数据库系统都在各个方面得到了广泛的应用。
数据和云
2019/08/26
7250
掌握后可为孩子收藏的MySQL入门全套
MySQL 入门全套
数据库(Database)是按照数据结构来组织、存储和管理数据的仓库,它产生于距今六十多年前,随着信息技术和市场的发展,特别是二十世纪九十年代以后,数据管理不再仅仅是存储和管理数据,而转变成用户所需要的各种数据管理的方式。数据库有很多种类型,从最简单的存储有各种数据的表格到能够进行海量数据存储的大型数据库系统都在各个方面得到了广泛的应用。
测试小兵
2019/11/19
6990
MySQL[一]
1·什么是MySQL丶Oracle丶SQLite丶Access丶MS SQL Server等?
Wyc
2018/09/11
8830
一、Mysql(1)
  数据库简介 人类在进化的过程中,创造了数字、文字、符号等来进行数据的记录,但是承受着认知能力和创造能力的提升,数据量越来越大,对于数据的记录和准确查找,成为了一个重大难题 计算机诞生后,数据开始在计算机中存储并计算,并设计出了数据库系统 数据库系统解决的问题:持久化存储,优化读写,保证数据的有效性 当前使用的数据库,主要分为两类 文档型,如sqlite,就是一个文件,通过对文件的复制完成数据库的复制 服务型,如mysql、postgre,数据存储在一个物理文件中,但是需要使用终端以tcp/ip协议连接
酱紫安
2018/04/16
9860
一、Mysql(1)
MySQL学习笔记
(MySQL官网下载地址:http://dev.mysql.com/downloads/mysql/)
Mirror王宇阳
2020/11/13
7910
MySQL学习笔记
MYSQL库,表,记录的基本操作
  mysql – 用户权限相关数据   test – 用于用户测试数据   information_schema – MySQL本身架构相关数据
全栈程序员站长
2022/07/21
1.7K0
MYSQL库,表,记录的基本操作
数据库之MySql建议收藏
   mysql是一种开放源代码的关系型数据库管理系统(RDBMS),是使用最常用的数据库管理语言–结构化查询语言(SQL)进行数据库管理。
全栈程序员站长
2022/07/14
9270
MySQL 教程上
MySQL 中使用 REGEXP 或 NOT REGEXP 运算符 (或 RLIKE 和 NOT RLIKE) 来操作正则表达式。
acc8226
2022/05/17
3.5K0
SQL系列之DDL/DCL语言
前言:前面王豆豆已经写了增删改查这四种软件测试人员必须要掌握的语句,以下是链接: 增删改查的增删改 增删改查的查之简单查询 增删改查的查之高级查询 今天王豆豆主要讲一下DDL和DCL语言,这些语句只需要了解即可,当然能够记住是最好的。 SQL语言主要分为以下四类: 数据定义语言(DDL): 用于下定义和管理数据对象(库,表,索引,视图),包括数据库,数据表等,例如:CREATE DROP ALTER等语句。 数据操作语言(DML): 用于操作数据库对象中包含的数据,例如:INSERT U
王豆豆
2018/06/08
1.1K0
21 分钟 MySQL 入门教程完整版
MySQL 为关系型数据库(Relational Database Management System), 这种所谓的"关系型"可以理解为"表格"的概念, 一个关系型数据库由一个或数个表格组成, 如图所示的一个表格:
数据STUDIO
2021/11/10
1.7K0
收藏|我的Mysql学习笔记
SQL是一个存活近半个世纪的语言,如今仍有大量人在使用。它语法简单,对培养数据整理和提取的思维有很大帮助。我将我过去的笔记分享给大家,希望能为大家的学习提供参考,更希望有人因此能迈出学习SQL的第一步~
刘早起
2020/05/13
1.3K0
收藏|我的Mysql学习笔记
SQL学习之MYSQL的常用命令和增删改查语句和数据类型
连接命令:mysql -h[主机地址] -u[用户名] -p[用户密码]  创建数据库:create database [库名]  显示所有数据库: show databases;  打开数据库:use [库名]  当前选择的库状态:SELECT DATABASE();  创建数据表:CREATE TABLE [表名]([字段名] [字段类型]([字段要求]) [字段参数], ......);  显示数据表字段:describe 表名;  当前库数据表结构:show tables;  更改表格     AL
Jetpropelledsnake21
2018/06/14
2.5K0
考前复习必备MySQL数据库(关系型数据库管理系统)
大家好,我是魔王哪吒,话不多说,今天带来的是一篇《考前复习必备MySQL数据库(关系型数据库管理系统)》文章,欢迎大家喜欢。
达达前端
2022/04/13
6.1K0
考前复习必备MySQL数据库(关系型数据库管理系统)
mysql系列一
学习mysql必备工具即安装mysql客户端;mysql安装教程在网上有很多,在此处就不在仔细说明;
沁溪源
2020/09/03
1K0
MySQL进阶之索引
索引是对数据库表中一个或多个列(例如,employee 表的姓名 (name) 列)的值进行排序的结构。如果想按特定职员的姓来查找他或她,则与在表中搜索所有的行相比,索引有助于更快地获取信息。
测试小兵
2019/11/19
4570
MySQL 学习一:新手一学就会,MySQL 零基础增删改查简单入门教程
MySQL 是一种开放源代码的关系型数据库管理系统(RDBMS),使用最常用的数据库管理语言--结构化查询语言(SQL)进行数据库管理。大多数人都认为在不需要事务化处理的情况下,MySQL 是管理内容最好的选择。在本文我将带大家从建库到操作具体数据一步一步来上手 MySQL,若有问题请在文章下方留言。
白鹿第一帅
2022/05/08
1.8K0
MySQL 学习一:新手一学就会,MySQL 零基础增删改查简单入门教程
3. SQL 与 MySQL 基础
我们平时所说的CRUD其实就是增删改查(Create/Retrieve/Update/Delete)
浪漫主义狗
2023/04/22
1.9K0
Mysql入门
主流数据库包括:MS SQL Server, Oracle,DB2,Informix, Sybase 等。
jinghong
2020/05/12
1.3K0
Mysql入门
MySQL入门详解(一)---mysql的语言
当客户端连接到服务器是,MySQL访问控制有两个阶段:连接验证 对用户名密码,请求验证 对权限验证
步履不停凡
2019/09/11
1.3K0
MySQL系列之数据库简介
数据库的定义有很多种,我的理解数据库就是一个特殊的文件夹,里面存放的是数据表;特殊的文件夹需要特定的方式打开操作;而不同公司开发出来的数据库功能和细节都不同,导致这种特定的方式也不同,使用数据库的学习成本就大大增加。
数据山谷
2020/11/25
5940
MySQL系列之数据库简介
相关推荐
掌握后可为孩子收藏的MySQL入门全套
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档