zoukankan      html  css  js  c++  java
  • mysql表分区技术

    一、什么是表分区
    通俗地讲表分区是将一大表,根据条件分割成若干个小表mysql5.1开始支持数据表分区了。
    如:某用户表的记录超过了600万条,那么就可以根据入库日期将表分区,也可以根据所在地将表分区。当然也可根据其他的条件分区。

    二、为什么要对表进行分区
    为了改善大型表以及具有各种访问模式的表的可伸缩性,可管理性和提高数据库效率。

    分区的一些优点包括:
          1)、与单个磁盘或文件系统分区相比,可以存储更多的数据
          2)、 对于那些已经失去保存意义的数据,通常可以通过删除与那些数据有关的分区,很容易地删除那些数据。相反地,在某些情况下,添加新数据的过程又可以通过为那 些新数据专门增加一个新的分区,来很方便地实现。通常和分区有关的其他优点包括下面列出的这些。MySQL分区中的这些功能目前还没有实现,但是在我们的 优先级列表中,具有高的优先级;我们希望在5.1的生产版本中,能包括这些功能。
          3)一些查询可以得到极大的优化这主要是借助于满足一个给定WHERE语句的数据可以只保存在一个或多个分区内,这样在查找时就不用查找其他剩余的分 区。因为分区可以在创建了分区表后进行修改,所以在第一次配置分区方案时还不曾这么做时,可以重新组织数据,来提高那些常用查询的效率。
          4)、涉及到例如SUM()和COUNT()这样聚合函数的查询,可以很容易地进行并行处理。这种查询的一个简单例子如 “SELECT salesperson_id, COUNT (orders) as order_total FROM sales GROUP BY salesperson_id;”。通过“并行”,这意味着该查询可以在每个分区上同时进行,最终结果只需通过总计所有分区得到的结果。
          5)、通过跨多个磁盘来分散数据查询,来获得更大的查询吞吐量。

    三、分区类型

     · RANGE分区:基于属于一个给定连续区间的列值,把多行分配给分区。
    · LIST分区:类似于按RANGE分区,区别在于LIST分区是基于列值匹配一个离散值集合中的某个值来进行选择。
    · HASH分区:基于用户定义的表达式的返回值来进行选择的分区,该表达式使用将要插入到表中的这些行的列值进行计算。这个函数可以包含MySQL 中有效的、产生非负整数值的任何表达式。
    · KEY分区:类似于按HASH分区,区别在于KEY分区只支持计算一列或多列,且MySQL 服务器提供其自身的哈希函数。必须有一列或多列包含整数值。

    下面主要介绍 RANG 和 HASH的用法   别的基本用不到

    • RANGE分区

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

           这些区间要连续且不能相互重叠,使用VALUES LESS THAN操作符来进行定义。以下是实例。

    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 NOT NULL,
        store_id INT NOT NULL
    )ENGINE=MyISAM DEFAULT CHARSET=utf8
    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)
    );
    

     按照这种分区方案,在商店1到5工作的雇员相对应的所有行被保存在分区P0中,商店6到10的雇员保存在P1中,依次类推。注意,每个分区都是按顺序进行定义,从最低到最高。这是PARTITION BY RANGE 语法的要求;在这点上,它类似于C或Java中的“switch ... case”语句。
           对于包含数据(72, 'Michael', 'Widenius', '1998-06-25', NULL, 13)的一个新行,可以很容易地确定它将插入到p2分区中,但是如果增加了一个编号为第21的商店,将会发生什么呢?在这种方案下,由于没有规则把 store_id大于20的商店包含在内,服务器将不知道把该行保存在何处,将会导致错误。 要避免这种错误,可以通过在CREATE TABLE语句中使用一个“catchall” VALUES LESS THAN子句,该子句提供给所有大于明确指定的最高值的值:

    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 NOT NULL,
        store_id INT NOT NULL
    )ENGINE=MyISAM DEFAULT CHARSET=utf8
    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 MAXVALUE
    );
    

     MAXVALUE 表示最大的可能的整数值。现在,store_id 列值大于或等于16(定义了的最高值)的所有行都将保存在分区p3中。在将来的某个时候,当商店数已经增长到25, 30, 或更多 ,可以使用ALTER TABLE语句为商店21-25, 26-30,等等增加新的分区。

    你还可以使用一个基于两个DATE (日期)中的一个的表达式来分割表数据。例如,假定你想基于每个雇员离开公司的年份来分割表,也就是说,YEAR(separated)的值。实现这种分区模式的CREATE TABLE 语句的一个例子如下所示:

    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
    )ENGINE=MyISAM DEFAULT CHARSET=utf8
    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中。

    RANGE分区在如下场合特别有用:
          1)、 当需要删除一个分区上的“旧的”数据时,只删除分区即可。 如果你使用上面最近的那个例子给出的分区方案,你只需简单地使用 “ALTER TABLE employees DROP PARTITION p0;”来删除所有在1991年前就已经停止工作的雇员相对应的所有行。对于有大量行的表,这比运行一个如“DELETE FROM employees WHERE YEAR (separated) <= 1990;”这样的一个DELETE查询要有效得多。
          2)、想要使用一个包含有日期或时间值,或包含有从一些其他级数开始增长的值的列。
          3)、经常运行直接依赖于用于分割表的列的查询。例如,当执行一个如“SELECT COUNT(*) FROM employees WHERE YEAR(separated) = 2000 GROUP BY store_id;”这样的查询时,MySQL可以很迅速地确定只有分区p2需要扫描,这是因为余下的分区不可能包含有符合该WHERE子句的任何记录。

    注释:这种优化还没有在MySQL 5.1源程序中启用,但是,有关工作正在进行中。

    • HASH分区         

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

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

    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
    )ENGINE=MyISAM DEFAULT CHARSET=utf8
    PARTITION BY HASH(store_id)
    PARTITIONS 4;
    

     如果没有包括一个PARTITIONS子句,那么分区的数量将默认为1。 例外: 对于NDB Cluster(簇)表,默认的分区数量将与簇数据节点的数量相同,

    这种修正可能是考虑任何MAX_ROWS 设置,以便确保所有的行都能合适地插入到分区中。

    注意:对没有分区并且已经有数据的 MyISAM 表,也可以使用分区技术,他会自己去把已经存在的数据分到不同的区里面。

    下面是实验:

    CREATE TABLE `haha2` (
      `id` int(11),
      `num` int(11),
      `name` varchar(255)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
    

     然后再表中插入几十万条数据,现在查看 data 文件夹下 haha2.MYD 大概有10MB左右 , haha2.MYI 为索引文件。然后执行

    ALTER TABLE `haha2`  PARTITION BY HASH(id)
    PARTITIONS 5;
    

     他会把原来的 haha2.MYD 中的数据平均分到五个文件中去。

  • 相关阅读:
    [Tips] kubeconfig合并
    某书补充题选做
    Card
    Ant Design Pro V5 使用 Cesium 地图开发包遇到加载widgets.css样式报错
    工作相关
    pc端谷歌浏览器长截图
    dao层与xml之间联系
    三周的大学生活,我到底是怎么过来的
    湖南大学推荐书《社会学大纲》阅读有感 其二
    湖南大学新生报到游记 其一
  • 原文地址:https://www.cnblogs.com/mr-amazing/p/3734288.html
Copyright © 2011-2022 走看看