MySQL分区表(优化)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介:

MySQL分区表(优化)

  原贴:http://www.cnblogs.com/freeton/p/4265228.html

  当数据库数据量涨到一定数量时,性能就成为我们不能不关注的问题,如何优化呢? 常用的方式不外乎那么几种:

  说明:innodb和MyIsam存储引擎都支持分区表功能。  

  1、分表,即把一个很大的表达数据分到几个表中,这样每个表数据都不多。 

    优点:提高并发量,减小锁的粒度

    缺点:代码维护成本高,相关sql都需要改动

  2、分区,所有的数据还在一个表中,但物理存储数据根据一定的规则存放在不同的文件中,文件也可以放到另外磁盘上

    优点:代码维护量小,基本不用改动,提高IO吞吐量

    缺点:表的并发程度没有增加

  3、拆分业务,这个本质还是分表。

    优点:长期支持更好

    缺点:代码逻辑重构,工作量很大

  当然,每种情况都有合适的应用场景,需要根据具体业务具体选择。由于分表和拆分业务和mysql本身关系不大属于业务层面,我们只说和数据库关系最紧密的方式:表分区。不过使用表分区有个前提就是你的数据库必须支持。那么,怎么知道我的数据库是否支持表分区呢? 请执行下面命令 

show plugins;  ---在mysql控制台中执行

据说5.4一下的版本是另外一个命令,不过我没有测试

 show variables like '%part%';

   数据库的表分区一般有两种方式:纵向和横向。纵向就是把表中不同字段分到不同数据文件中。横向是把表中前一部分数据放到一个文件中,另一部分数据放到一个文件中。mysql只支持后后一种方式,横向拆分。

1、创建分区表

   如果要使用表的分区优势,不但要数据库版本支持分区,关键要建分区表,这个表和普通表不一样,并且必须建表的时候就要指定分区,否则无法把普通表改成分区表。那么,如果创建一个分区表呢?其他很简单,请看下面建表语句

CREATE  TABLE `T_part` (

    `f_id` INT  DEFAULT NULL,

    `f_name`  VARCHAR (20) DEFAULT NULL,

    PRIMARY KEY (`f_id`)

)  ENGINE = myisam DEFAULT CHARSET = utf8

PARTITION BY RANGE (`f_id`)(       

     PARTITION p0  VALUES less  THAN (10),

     PARTITION p1  VALUES less  THAN (20)

);

 

 

 

 

 

-----指定分区方式

-- 分了两个区。p0为第1个分区表

--  p1是第2个分区表的名称。

 

insert   into   T_part(f_id)   values(1),(5),(10),(12),(15),(22);

插入数据测试

上面语句建了一个“T_part”表,有两个字段f_id和f_name,并且根据RANGE方式把表分成两个区p0、p1,当f_id小于10放入p0分区,当f_id大于0小于20放入分区p1. 那么当f_id大于20的数据放入哪个分区呢? 你猜对了,insert语句会报错。

分区表文件在/var/lib/mysql/库名  的目录中可以看得到。

     看到了吧,创建分区表就这么简单!当然,你随时可以添加删除分区,不过要注意,删除分区的时候会把当前分区下所有数据都删除。

altertable T_part add partition(partition p2 values less than (MAXVALUE));  ---新增分区
altertable T_part DROP partition p2; ----删除分区

 

2、表分区的几种方式

   mysql支持5种分区方式:RANGE分区、LIST分区、HASH分区、LINEARHASH分区和KEY分区。每种分区都有自己的使用场景。

  1)RANGE分区:

    RANGE分区的表是通过如下一种方式进行分区的,每个分区包含那些分区表达式的值位于一个给定的连续区间内的行。这些区间要连续且不能相互重叠,使用VALUES LESS THAN操作符来进行定义。

    上面的例子就是RANGE分区.

  2)LIST分区:

    MySQL中的LIST分区在很多方面类似于RANGE分区。和按照RANGE分区一样,每个分区必须明确定义。它们的主要区别在于,LIST分区中每个分区的定义和选择是基于某列的值从属于一个值列表集中的一个值,而RANGE分区是从属于一个连续区间值的集合。LIST分区通过使用“PARTITION BY LIST(expr)”来实现,其中“expr” 是某列值或一个基于某个列值、并返回一个整数值的表达式,然后通过“VALUES IN (value_list)”的方式来定义每个分区,其中“value_list”是一个通过逗号分隔的整数列表。

CREATE  TABLE  `T_list` (

    `f_id` INT DEFAULT NULL,

    `f_name` VARCHAR (20) DEFAULT NULL,

    PRIMARY KEY (`f_id`)

)  ENGINE = myisam DEFAULT CHARSET = utf8

PARTITION by list(`f_id`)

(

   PARTITION p0 VALUES in(1,2,3),

   PARTITION p1 VALUES in(4,5,6)

);

 

 

 

 

 

 

 

----区间值不能重复

 

 

 

3)HASH分区:

    HASH分区主要用来确保数据在预先确定数目的分区中平均分布。在RANGE和LIST分区中,必须明确指定一个给定的列值或列值集合应该保存在哪个分区中;而在HASH分区中,MySQL 自动完成这些工作,你所要做的只是基于将要被哈希的列值指定一个列值或表达式,以及指定被分区的表将要被分割成的分区数量。要使用HASH分区来分割一个表,要在CREATE TABLE 语句上添加一个“PARTITION BY HASH (expr)”子句,其中“expr”是一个返回一个整数的表达式。它可以仅仅是字段类型为MySQL 整型的一列的名字。此外,你很可能需要在后面再添加一个“PARTITIONSnum”子句,其中num 是一个非负的整数,它表示表将要被分割成分区的数量。

CREATE  TABLE `T_hash` (

    `f_id` INT DEFAULT NULL,

    `f_name` VARCHAR (20) DEFAULT NULL,

    PRIMARY KEY (`f_id`)

)  ENGINE = myisam DEFAULT CHARSET = utf8

PARTITION BY HASH(`f_id`)

PARTITIONS 4;

 

 

 

 

 

---可以指定多列

---分区个数

 /var/lib/mysql/库名  可以看到T_hash这个表存在4个分区表

 

“expr”还可以是MySQL 中有效的任何函数或其他表达式,只要它们返回一个既非常数、也非随机数的整数。(换句话说,它既是变化的但又是确定的)。但是应当记住,每当插入或更新(或者可能删除)一行,这个表达式都要计算一次;这意味着非常复杂的表达式可能会引起性能问题,尤其是在执行同时影响大量行的运算(例如批量插入)的时候。最有效率的哈希函数是只对单个表列进行计算,并且它的值随列值进行一致地增大或减小,因为这考虑了在分区范围上的“修剪”。也就是说,表达式值和它所基于的列的值变化越接近,MySQL就可以越有效地使用该表达式来进行HASH分区。

  4)LINEAR HASH分区:

    MySQL还支持线性哈希功能,它与常规哈希的区别在于,线性哈希功能使用的一个线性的2的幂(powers-oftwo)运算法则,而常规 哈希使用的是求哈希函数值的模数。线性哈希分区和常规哈希分区在语法上的唯一区别在于,在“PARTITION BY” 子句中添加“LINEAR”关键字.

  5)KEY分区:

    按照KEY进行分区类似于按照HASH分区,除了HASH分区使用的用户定义的表达式,而KEY分区的 哈希函数是由MySQL 服务器提供。MySQL 簇(Cluster)使用函数MD5()来实现KEY分区;对于使用其他存储引擎的表,服务器使用其自己内部的哈希函数,这些函数是基于与PASSWORD()一样的运算法则。

    KEY分区的语法和HASH语法类似,只是把关键字改成KEY。 

CREATE  TABLE `T_key` (

    `f_id` INT DEFAULT NULL,

    `f_name` VARCHAR (20) DEFAULT NULL,

    PRIMARY KEY (`f_id`)

)  ENGINE = myisam DEFAULT CHARSET = utf8

PARTITION BY LINEAR key(`f_id`)

PARTITIONS 3;


 6)子分区:

    子分区的意思就是在分区的基础上再次分区。且每个分区必须有相同个数的子分区。

CREATE  TABLE `T1_part` (

    `f_id` INT DEFAULT NULL,

    `f_name` VARCHAR (20) DEFAULT NULL,

    PRIMARY KEY (`f_id`)

) ENGINE=myisam

PARTITION  BY RANGE (`f_id`)

SUBPARTITION  BY HASH(`F_ID`)

SUBPARTITIONS  2

(

    PARTITION p0     VALUES       less THAN (10),

    PARTITION p1    VALUES        less THAN (20)

);


 

上面语句的意思是,建立两个range分区,每个分区根据hash有分别有两个子分区,实际上整个表分成2×2=4个分区。当然,要详细定义每个分区属性也是可以的

准备工作:创建存储数据、索引的目录:mkdir  -pv   /disk{0,1}/{data,idx}

CREATE  TABLE `T2_part` (

    `f_id` INT DEFAULT NULL,

    `f_name` VARCHAR (20) DEFAULT NULL,

    PRIMARY KEY (`f_id`)

) ENGINE=innodb

PARTITION BY RANGE (`f_id`)

SUBPARTITION BY HASH(`F_ID`)

(

    PARTITION p0     VALUES less THAN  (10)

     (

         SUBPARTITION s0

            DATA DIRECTORY = '/disk0/data'

            INDEX DIRECTORY = '/disk0/idx',

         SUBPARTITION s1

            DATA DIRECTORY = '/disk1/data'

            INDEX DIRECTORY = '/disk1/idx'

     ),

    PARTITION p1    VALUES less THAN  (20)

     (

         SUBPARTITION s2

            DATA DIRECTORY = '/disk0/data'

            INDEX DIRECTORY = '/disk0/idx',

         SUBPARTITION s3

            DATA DIRECTORY = '/disk1/data'

            INDEX DIRECTORY = '/disk1/idx'

     )

);


 

这样可以对每个分区指定具体存储磁盘。前提磁盘是存在的。

 

  MySQL 中的分区在禁止空值(NULL)上没有进行处理,无论它是一个列值还是一个用户定义表达式的值。一般而言,在这种情况下MySQL 把NULL视为0。如果你希望回避这种做法,你应该在设计表时不允许空值;最可能的方法是,通过声明列“NOT NULL”来实现这一点。




      本文转自rshare 51CTO博客,原文链接:http://blog.51cto.com/1364952/1954668 ,如需转载请自行联系原作者





相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
MySQL原理简介—6.简单的生产优化案例
本文介绍了数据库和存储系统的几个主题: 1. **MySQL日志的顺序写和数据文件的随机读指标**:解释了磁盘随机读和顺序写的原理及对数据库性能的影响。 2. **Linux存储系统软件层原理及IO调度优化原理**:解析了Linux存储系统的分层架构,包括VFS、Page Cache、IO调度等,并推荐使用deadline算法优化IO调度。 3. **数据库服务器使用的RAID存储架构**:介绍了RAID技术的基本概念及其如何通过多磁盘阵列提高存储容量和数据冗余性。 4. **数据库Too many connections故障定位**:分析了MySQL连接数限制问题的原因及解决方法。
MySQL进阶突击系列(07) 她气鼓鼓递来一条SQL | 怎么看执行计划、SQL怎么优化?
在日常研发工作当中,系统性能优化,从大的方面来看主要涉及基础平台优化、业务系统性能优化、数据库优化。面对数据库优化,除了DBA在集群性能、服务器调优需要投入精力,我们研发需要负责业务SQL执行优化。当业务数据量达到一定规模后,SQL执行效率可能就会出现瓶颈,影响系统业务响应。掌握如何判断SQL执行慢、以及如何分析SQL执行计划、优化SQL的技能,在工作中解决SQL性能问题显得非常关键。
深入解析MySQL的EXPLAIN:指标详解与索引优化
MySQL 中的 `EXPLAIN` 语句用于分析和优化 SQL 查询,帮助你了解查询优化器的执行计划。本文详细介绍了 `EXPLAIN` 输出的各项指标,如 `id`、`select_type`、`table`、`type`、`key` 等,并提供了如何利用这些指标优化索引结构和 SQL 语句的具体方法。通过实战案例,展示了如何通过创建合适索引和调整查询语句来提升查询性能。
577 9
MySQL底层概述—8.JOIN排序索引优化
本文主要介绍了MySQL中几种关键的优化技术和概念,包括Join算法原理、IN和EXISTS函数的使用场景、索引排序与额外排序(Using filesort)的区别及优化方法、以及单表和多表查询的索引优化策略。
MySQL底层概述—8.JOIN排序索引优化
大厂面试官:聊下 MySQL 慢查询优化、索引优化?
MySQL慢查询优化、索引优化,是必知必备,大厂面试高频,本文深入详解,建议收藏。关注【mikechen的互联网架构】,10年+BAT架构经验分享。
大厂面试官:聊下 MySQL 慢查询优化、索引优化?
MySQL底层概述—7.优化原则及慢查询
本文主要介绍了:Explain概述、Explain详解、索引优化数据准备、索引优化原则详解、慢查询设置与测试、慢查询SQL优化思路
115 15
MySQL底层概述—7.优化原则及慢查询
MySQL底层概述—5.InnoDB参数优化
本文介绍了MySQL数据库中与内存、日志和IO线程相关的参数优化,旨在提升数据库性能。主要内容包括: 1. 内存相关参数优化:缓冲池内存大小配置、配置多个Buffer Pool实例、Chunk大小配置、InnoDB缓存性能评估、Page管理相关参数、Change Buffer相关参数优化。 2. 日志相关参数优化:日志缓冲区配置、日志文件参数优化。 3. IO线程相关参数优化: 查询缓存参数、脏页刷盘参数、LRU链表参数、脏页刷盘相关参数。
MySQL底层概述—5.InnoDB参数优化
基于SQL Server / MySQL进行百万条数据过滤优化方案
对百万级别数据进行高效过滤查询,需要综合使用索引、查询优化、表分区、统计信息和视图等技术手段。通过合理的数据库设计和查询优化,可以显著提升查询性能,确保系统的高效稳定运行。
35 9
MySQL和SQLSugar百万条数据查询分页优化
在面对百万条数据的查询时,优化MySQL和SQLSugar的分页性能是非常重要的。通过合理使用索引、调整查询语句、使用缓存以及采用高效的分页策略,可以显著提高查询效率。本文介绍的技巧和方法,可以为开发人员在数据处理和查询优化中提供有效的指导,提升系统的性能和用户体验。掌握这些技巧后,您可以在处理海量数据时更加游刃有余。
80 9
从MySQL优化到脑力健康:技术人与效率的双重提升
聊到效率这个事,大家应该都挺有感触的吧。 不管是技术优化还是个人状态调整,怎么能更快、更省力地完成事情,都是我们每天要琢磨的事。
66 23
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等