zoukankan      html  css  js  c++  java
  • MySQL 表的分区

    如何判断当前MySQL是否支持分区

    命令:show variables like '%partition%' 运行结果:

    mysql> show variables like '%partition%';

    +-------------------+-------+

    | Variable_name | Value |

    +-------------------+-------+

    | have_partitioning | YES |

    +-------------------+-------+

    1 row in set (0.00 sec)

    have_partintioning 的值为YES,表示支持分区。

    分区类型

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

    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 RANGE (YEAR(separated)) (

        PARTITION p0 VALUES LESS THAN (1991),

        PARTITION p1 VALUES LESS THAN (1996),

        PARTITION p2 VALUES LESS THAN (2001),

        PARTITION p3 VALUES LESS THAN MAXVALUE

    );

    在这个方案中,在1991年前雇佣的所有雇员的记录保存在分区p0中,1991年到1995年期间雇佣的所有雇员的记录保存在分区p1中, 1996年到2000年期间雇佣的所有雇员的记录保存在分区p2中,2000年后雇佣的所有工人的信息保存在p3中。

    MAXVALUE 表示最大的可能的整数值,在VALUES LESS THAN 子句中使用一个表达式也是可能的。这里最值得注意的限制是MySQL 必须能够计算表达式的返回值作为LESS THAN (<) 比较的一部分;因此,表达式的值不能为NULL 。由于这个原因,分区表字段定义为非空(NOT NULL)。

    错误原因: 常量、随机或者依赖时区的表达式不能作为分区函数( Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed ),RANGE 中的字段换成 datetime/date 类型,创建成功。

    //新增一个分区

    ALTER TABLE foo_range ADD PARTITION(

        PARTITION p4 VALUES LESS THAN (THAN ('2017'))

    );

    // 删除分区

    ALTER TABLE employees DROP PARTITION p0;

    // 查询分区

    explain partitions select * from city_partG

     

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

    LIST分区通过使用“PARTITION BY LIST(expr)”来实现,其中“expr”是某列值或一个基于某个列值、并返回一个整数值的表达式,然后通过“VALUES IN (value_list)”的方式来定义每个分区,其中“value_list”是一个通过逗号分隔的整数列表。 注释:在MySQL 5.1中,当使用LIST分区时,有可能只能匹配整数列表。LIST 中的字段必须是包含主键( A PRIMARY KEY must include all columns in the table's partitioning function)

    Sql代码:

    CREATE TABLE T1 (
    id int(8) NOT NULL AUTO_INCREMENT,
    createtime datetime NOT NULL,
    PRIMARY KEY (id,createtime)
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
    PARTITION BY RANGE(TO_DAYS (createtime))
    (
    PARTITION p0 VALUES LESS THAN (TO_DAYS('2010-04-15')),
    PARTITION p1 VALUES LESS THAN (TO_DAYS('2010-05-01')),
    PARTITION p2 VALUES LESS THAN (TO_DAYS('2010-05-15')),
    PARTITION p3 VALUES LESS THAN (TO_DAYS('2010-05-31')),
    PARTITION p4 VALUES LESS THAN (TO_DAYS('2010-06-15')),
    PARTITION p19 VALUES LESS ThAN MAXVALUE);

    要重点注意的是,LIST分区没有类似如“VALUES LESS THAN MAXVALUE”这样的包含其他值在内的定义。将要匹配的任何值都必须在值列表中找到。

    // 删除分区

    ALTER TABLE employees DROP PARTITION pWest

     

    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 NULL DEFAULT '1970-01-01',

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

        job_code INT,

        store_id INT

    )

    PARTITION BY HASH(store_id)

    PARTITIONS 4;

    HASH分区主要用来确保数据在预先确定数目的分区中平均分布。在RANGE和LIST分区中,必须明确指定一个给定的列值或列值集合应该保存在哪个分区中。 
    在HASH分区中,MySQL 自动完成这些工作,你所要做的只是基于将要被哈希的列值指定一个列值或表达式,以及指定被分区的表将要被分割成的分区数量。

     

    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 NULL DEFAULT '1970-01-01',

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

        job_code INT,

        store_id INT

    )

    PARTITION BY LINEAR HASH(YEAR(hired))

    PARTITIONS 4;

    假设一个表达式expr, 当使用线性哈希功能时,记录将要保存到的分区是num个分区中的分区N,其中N是根据下面的算法得到: 

    找到下一个大于num的2的幂,我们把这个值称为V ,它可以通过下面的公式得到: 

    V = POWER(2, CEILING(LOG(2, num)))

    (例如,假定num是13。那么LOG(2,13)就是3.7004397181411。 CEILING(3.7004397181411)就是4,则V = POWER(2,4), 即等于16)。 

    设置 N = F(column_list) & (V - 1)

    当 N >= num:

    设置 V = CEIL(V / 2) 

    设置 N = N & (V - 1) 

    线性哈希分区的优点在于增加、删除、合并和拆分分区将变得更加快捷,有利于处理含有极其大量(1000 )数据的表。它的缺点在于,与使用常规HASH分区得到的数据分布相比,各个分区间数据的分布不大可能均衡。

    相关文章:MySQL数据库分区 linear hash分区(五)

     

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

    Sql代码:

    CREATE TABLE tk (

        col1 INT NOT NULL,

        col2 CHAR(5),

        col3 DATE

    )

    PARTITION BY LINEAR KEY (col1)

    PARTITIONS 3;

    在KEY分区中使用关键字LINEAR和在HASH分区中使用具有同样的作用,分区的编号是通过2的幂(powers-of-two)算法得到,而不是通过模数算法。

    注意:无论使用何种类型的分区,分区总是在创建时就自动的顺序编号,且从0开始记录,记住这一点非常重要。表的所有分区必须有唯一的名字。

     

    分区限制:

    • 分区表达式中不允许以下构造:
      • 存储过程,存储函数,用户自定义函数或插件。
      • 声明的变量或用户变量
    • 分区表达式中允许使用算术运算符 +, -和 *,但是,结果必须是一个整数值或NULL。
    • 禁止更改服务器SQL模式
      • 使用用户定义的分区的表在创建时不会保留有效的SQL模式。如本手册其他部分所述(请参见 第5.1.11节“服务器SQL模式”),许多MySQL函数和运算符的结果可能会根据服务器SQL模式而变化。因此,在创建分区表之后随时更改SQL模式可能会导致此类表的行为发生重大变化,并且很容易导致数据损坏或丢失。由于这些原因,强烈建议您不要在创建分区表之后更改服务器SQL模式。
    • 最大分区数为8192。此数目包括子分区。(根据不同MySQL版本可能会有不同限制)
    • 分区的InnoDB表不支持外键
    • 排序问题
      • ALTER TABLE ... ORDER BY, 针对分区表运行 的语句仅导致每个分区内的行排序。 
    • 分区表不支持FULLTEXT 索引或搜索。
    • 在innodb数据库引擎中要把表设置为独立表空间。
    • 分区键可能不是子查询,即使该子查询解析为整数值或NULL
    • 分区键必须是整数列或解析为整数的表达式。ENUM不能使用采用列的表达式 列或表达式值也可以是NULL请参见第23.2.7节“ MySQL分区如何处理NULL”
    • 分区必须使用HASH或 KEY分区。只有 RANGELIST分区可以再分区;HASH并且 KEY分区不能再分区。

    相关文章:MySQL表的四种分区类型

         Mysql数据库表分区深入详解

                   MySQL数据库分区简介(一)

  • 相关阅读:
    Bzoj1072--Scoi2007排列perm
    Bzoj1041--Haoi2008圆上的整点
    Bzoj3932--Cqoi2015任务查询系统
    HDU 1024 Max Sum Plus Plus(DP)
    HDU 1029 Ignatius and the Princess IV
    【noip模拟题】数列
    Hello World
    vue-router 进阶
    vue2.0 源码解读(二)
    vue2.0 源码解读(一)
  • 原文地址:https://www.cnblogs.com/xuey/p/9082261.html
Copyright © 2011-2022 走看看