mysql分区表的理解与想法

Mysql在创建表时使用partition by子句定义每个分区存放的数据,将数据安装一个较粗的刻度分在不同的表中。这样做可以将相关的树存放在一起,另外如果想一次批量删除整个分区的数据也将变的方便。

使用场景:

1、 表非常大以至于无法将全部的数据放在内存中或者表中的最后部分的数据才是热数据其他都是历史数据;

2、 分区表的数据可以放在不同的物理机上,更好的利用多个硬件设备;

3、 使用分区表来比年某些特殊的瓶颈,如innoDB的单个索引的互斥访问;

优势:

1、与单个磁盘或文件系统分区相比,可以存储更多的数据。

2、对于那些已经失去保存意义的数据,通常可以通过删除与那些数据有关的分区,很容易地删除那些数据。相反地,在某些情况下,添加新数据的过程又可以通过为那些新数据专门增加一个新的分区,来很方便地实现。通常和分区有关的其他优点包括下面列出的这些。MySQL分区中的这些功能目前还没有实现,但是在我们的优先级列表中,具有高的优先级;

 3、一些查询可以得到极大的优化,这主要是借助于满足一个给定WHERE语句的数据可以只保存在一个或多个分区内,这样在查找时就不用查找其他剩余的分区。因为分区可以在创建了分区表后进行修改,所以在第一次配置分区方案时还不曾这么做时,可以重新组织数据,来提高那些常用查询的效率。

4、涉及到例如SUM()和COUNT()这样聚合函数的查询,可以很容易地进行并行处理。这种查询的一个简单例子如 “SELECT salesperson_id, COUNT (orders) as order_total FROM sales

GROUP BY salesperson_id;”。通过“并行”,这意味着该查询可以在每个分区上同时进行,最终结果只需通过总计所有分区得到的结果。

5、通过跨多个磁盘来分散数据查询,来获得更大的查询吞吐量。

分区表的原理

数据库表分区把一个大的物理表分成若干个小的物理表,并使得这些小物理表在逻辑上可以被当成一张表来使用。

Select操作:想要充分的返回分区的优势,查询的条件一定要有分区的字段,这边优化器才可以过滤不需要的部分分区;

Insert操作和delete操作:分区层先打开所有的底层表,确认那个分区接收,在将记录写入底层表;

Update操作:分区层先打开所有的底层表,确认那个分区接收,将数据拿出更新,然后确认是那个分区,将数据写入,原数据删除操作;

虽然每一个操作很多回先打开锁住所有的底层表,但这并不代表在处理过程中是锁住全表的。如果存储引擎能够自己实现行级锁(innoDB),则会在分区层释放对应的表锁,所以建议使用类似innodb的引擎;

分区表的类型

1RANGE分区:基于属于一个给定连续区间的列值,把多行分配给分区。

2LIST分区:类似于按RANGE分区,区别在于LIST分区是基于列值匹配一个离散值集合中的某个值来进行选择。

3HASH分区:基于用户定义的表达式的返回值来进行选择的分区,该表达式使用将要插入到表中的这些行的列值进行计算。这个函数可以包含MySQL 中有效的、产生非负整数值的任何表达式。

4KEY分区:类似于按HASH分区,区别在于KEY分区只支持计算一列或多列,且MySQL服务器提供其自身的哈希函数。必须有一列或多列包含整数值。

RANGE分区

基于属于一个给定连续区间的列值,把多行分配给分区;使用values less than操作符来定义;

Sql如下:

CREATE TABLE employees (

   id INT NOT NULL,

   hired DATE NOT NULL DEFAULT '1970-01-01',

   separated DATE NOT NULL DEFAULT '9999-12-31',

   job_code INT NOT NULL,

   store_id INT NOT NULL

)

partition BY RANGE (store_id) (

   partition p0 VALUES LESS THAN (6),

   partition p1 VALUES LESS THAN (11),

   partition p2 VALUES LESS THAN (16),

   partition p3 VALUES LESS THAN (21)

);

这边以员工表中的门店id为分区依据:p0为store_id小于6的数据,那store_id大于20会如何?

直接报错,为了避免上图的问题,可以在建表的时候加上 values less

than maxvalue,将最大的值放入另外一张表;

Sql如下:

CREATE TABLE employees (

   id INT NOT NULL,

   hired DATE NOT NULL DEFAULT '1970-01-01',

   separated DATE NOT NULL DEFAULT '9999-12-31',

   job_code INT NOT NULL,

   store_id INT NOT NULL

)

partition BY RANGE (store_id) (

   partition p0 VALUES LESS THAN (6),

   partition p1 VALUES LESS THAN (11),

   partition p2 VALUES LESS THAN (16),

partition p3

VALUES LESS THAN (21),

partition p4values less than maxvalue;

);

这边的话,当store_id大于21的时候,数据就会加入到p4中;这样来看,range有点类似与java当中的SWTICH case;

List分区

类似于按RANGE分区,区别在于LIST分区是基于列值匹配一个离散值集合中的某个值来进行选择。

LIST分区通过使用“PARTITION

BY LIST(expr)”来实现,其中“expr”是某列值或一个基于某个列值、并返回一个整数值的表达式,然后通过“VALUES IN (value_list)”的方式来定义每个分区,其中“value_list”是一个通过逗号分隔的整数列表。

Sql代码:

CREATE TABLE employees (

    id INT NOT NULL,

    fname VARCHAR(30),

    lname VARCHAR(30),

    hired DATE NOT NULL DEFAULT '1970-01-01',

    separated DATE NOT NULL DEFAULT '9999-12-31',

    job_code INT,

    store_id INT

)

PARTITION BY LIST(store_id)

    PARTITION pNorth VALUES IN (3,5,6,9,17),

    PARTITION pEast VALUES IN (1,2,10,11,19,20),

    PARTITION pWest VALUES IN (4,12,13,14,18),

    PARTITION pCentral VALUES IN (7,8,15,16)

)

假定有20个音像店,分布在4个有经销权的地区,如下表所示:

地区     商店ID 号

北区3, 5, 6, 9, 17

东区1, 2, 10, 11, 19, 20

西区4, 12, 13, 14, 18

中心区7, 8,15, 16

这样的话,会根据插入的store_id,插入到对应的分区,指得注意的是如果插入了store_id=21的,将会报错,也没有类似range的 less than maxvalue的功能;

HASH分区

基于用户定义的表达式的返回值来进行选择的分区,该表达式使用将要插入到表中的这些行的列值进行计算。这个函数可以包含MySQL 中有效的、产生非负整数值的任何表达式。

要使用HASH分区来分割一个表,要在CREATE TABLE 语句上添加一个“PARTITION BY HASH (expr)”子句,其中“expr”是一个返回一个整数的表达式。它可以仅仅是字段类型为MySQL整型的一列的名字。此外,你很可能需要在后面再添加一个“PARTITIONS

num”子句,其中num是一个非负的整数,它表示表将要被分割成分区的数量。

Sql代码:

CREATE TABLE employees (

    id INT NOT NULL,

    fname VARCHAR(30),

    lname VARCHAR(30),

    hired DATE NOT NULLDEFAULT '1970-01-01',

    separated DATE NOT NULLDEFAULT '9999-12-31',

    job_code INT,

    store_id INT

)

PARTITION BY HASH(store_id)

PARTITIONS 4;

如果没有包括一个PARTITIONS子句,那么分区的数量将默认为1。例外:对于NDB Cluster(簇)表,默认的分区数量将与簇数据节点的数量相同,这种修正可能是考虑任何MAX_ROWS设置,以便确保所有的行都能合适地插入到分区中。

LINER HASH

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

Sql代码:

CREATE TABLE employees (

    id INT NOT NULL,

    fname VARCHAR(30),

    lname VARCHAR(30),

    hired DATE NOT NULLDEFAULT '1970-01-01',

    separated DATE NOT NULLDEFAULT '9999-12-31',

    job_code INT,

    store_id INT

)

PARTITION BY LINEAR HASH(YEAR(hired))

PARTITIONS 4;

1. 它的优点是在数据量大的场景,譬如TB级,增加、删除、合并和拆分分区会更快,缺点是,相对于HASH分区,它数据分布不均匀的概率更大。

KSY分区

类似于按HASH分区,区别在于KEY分区只支持计算一列或多列,且MySQL服务器提供其自身的哈希函数。必须有一列或多列包含整数值。

总结:

1.    MySQL分区中如果存在主键或唯一键,则分区列必须包含在其中。优化器会根据分区函数来过滤一些分区,通过过滤分区让查询扫描的数据变少;如果没有的话就有访问全表;

可以使用explain partitions select *from ** 来知道sql语句是否用了分区,如下图:

2. 对于原生的RANGE分区,LIST分区,HASH分区,分区对象返回的只能是整数值。

3. RANGE COLUMNS,LIST COLUMNS,KEY,LINEAR KEY分区对象只能是列,不能是基于列的表达式。

4.分区的值为null值会是分区过滤无效,记录会放在第一个分区;建议创建第一个分区为无效分区,例如创建一个partition by range(col)(partition p0 less than 0,**),达到第一个无法过滤的数据很小;

查询优化

1、 查询的时候,where一定要带上分区列,且只能是列本身(和独立索引相似),如果是列的函数,优化器将过滤不出分区:如下图

2、分区表关联操作中的第二张表,关联条件需要是分区键,这样的话mysql会在对应的分区里面匹配行;

问题

1、实际生产环境下,分区需要实时的增加,如使用range类型的,按时间分区;这样的话必然导致分区越来越多(按官方上说mysql支持1024个分区),或者不增加分区的话(maxvalue的数据越来越多),所以个人的想法是:

每一段时间通过语句:-- 删除分区

alter table employees REMOVE PARTITIONING ;删除分区,数据不会删除

然后在去创建分区,保证热点(最近)数据在分区里面;语句为:

#新增分区

ALTER TABLE 表名 add PARTITION (PARTITION 分区名 VALUES LESS THAN (规则));

各位有什么好的想法?

 

最后数据大于千万级,单表优化之后还是慢?可以适当考虑分表分库操作,随之带来的是逻辑的直线上升;

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容

  • 原文链接 http://blog.csdn.net/kobejayandy/article/details/547...
    lucode阅读 894评论 0 0
  • MYSQL在创建表时使用PATITION BY子句定义每个分区存放的数据。在执行查询时,优化器会过滤那些没有我们需...
    阿长_一个程序员阅读 633评论 0 0
  • 摘要:MySQL分区表概述 随着MySQL越来越流行,Mysql里面的保存的数据也越来越大。在日常的工作中,我们经...
    暖夏未眠丶阅读 419评论 0 1
  • 一,什么是数据库分区前段时间写过一篇关于mysql分表的的文章,下面来说一下什么是数据库分区,以mysql为例。m...
    MrKai平凡之路阅读 1,155评论 0 5
  • mysql分区 Mysql支持水平分区,并不支持垂直分区;水平分区:指将同一表中不同行的记录分配到不同的物理文件中...
    Gundy_阅读 882评论 0 2