`

(转)mysql水平分表和垂直分表和数据库分区

 
阅读更多

坚信数据库的物理设计在对高级数据库的性能影响上远比其他因素重要。给大家说一下经过专家对Oracle的研究,他们解释了为什么拙劣的物理设计是数据库停机(无论是有计划的还是没计划的)背后的主要原因。但在这点上俺还是坚持DBA如果想要高性能的数据库就必须在数据库的物理设计上多思考的观点,这样才能减少响应时间使终端用户满意而不是引来骂声一片。

今天的文章是MySQL5.1的发布带来了设计超强动力数据库的强有力的武器,任何MySQL的DBA都应该尽快学习并使用它。俺觉得如果能很好滴使用这个5.1版带来的新特性,DBA可以使自己管理的VLDB(不知道什么是VLDB?告诉你,是好大好大的数据库的意思,Very Large DB)或数据仓库奇迹般的获得巨大的性能提升。

什么是数据库分区?

数据库分区是一种物理数据库设计技术,DBA和数据库建模人员对其相当熟悉。虽然分区技术可以实现很多效果,但其主要目的是为了在特定的SQL操作中减少数据读写的总量以缩减响应时间。

分区主要有两种形式://这里一定要注意行和列的概念(row是行,column是列)

水平分区(Horizontal Partitioning) 这种形式分区是对表的行进行分区,通过这样的方式不同分组里面的物理列分割的数据集得以组合,从而进行个体分割(单分区)或集体分割(1个或多个分区)。所有在表中定义的列在每个数据集中都能找到,所以表的特性依然得以保持。 

举个简单例子:一个包含十年发票记录的表可以被分区为十个不同的分区,每个分区包含的是其中一年的记录。(注:这里具体使用的分区方式我们后面再说,可以先说一点,一定要通过某个属性列来分割,譬如这里使用的列就是年份)

垂直分区(Vertical Partitioning) 这种分区方式一般来说是通过对表的垂直划分来减少目标表的宽度,使某些特定的列被划分到特定的分区,每个分区都包含了其中的列所对应的行。 

举个简单例子:一个包含了大text和BLOB列的表,这些text和BLOB列又不经常被访问,这时候就要把这些不经常使用的text和BLOB了划分到另一个分区,在保证它们数据相关性的同时还能提高访问速度。

在数据库供应商开始在他们的数据库引擎中建立分区(主要是水平分区)时,DBA和建模者必须设计好表的物理分区结构,不要保存冗余的数据(不同表中同时都包含父表中的数据)或相互联结成一个逻辑父对象(通常是视图)。这种做法会使水平分区的大部分功能失效,有时候也会对垂直分区产生影响。

在MySQL 5.1中进行分区

     MySQL5.1中最激动人心的新特性应该就是对水平分区的支持了。这对MySQL的使用者来说确实是个好消息,而且她已经支持分区大部分模式:

         Range(范围) C 这种模式允许DBA将数据划分不同范围。例如DBA可以将一个表通过年份划分成三个分区,80年代(1980's)的数据,90年代(1990's)的数据以及任何在2000年(包括2000年)后的数据。 

         Hash(哈希) C 这中模式允许DBA通过对表的一个或多个列的Hash Key进行计算,最后通过这个Hash码不同数值对应的数据区域进行分区,。例如DBA可以建立一个对表主键进行分区的表。 

         Key(键值) C 上面Hash模式的一种延伸,这里的Hash Key是MySQL系统产生的。 

         List(预定义列表) C 这种模式允许系统通过DBA定义的列表的值所对应的行数据进行分割。例如:DBA建立了一个横跨三个分区的表,分别根据2004年2005年和2006年值所对应的数据。 

         Composite(复合模式) - 很神秘吧,哈哈,其实是以上模式的组合使用而已,就不解释了。举例:在初始化已经进行了Range范围分区的表上,我们可以对其中一个分区再进行hash哈希分区。 

    分区带来的好处太多太多了,有多少?俺也不知道,自己猜去吧,要是觉得没有多少就别用,反正俺也不求你用。不过在这里俺强调两点好处:

性能的提升(Increased performance) - 在扫描操作中,如果MySQL的优化器知道哪个分区中才包含特定查询中需要的数据,它就能直接去扫描那些分区的数据,而不用浪费很多时间扫描不需要的地方了。需要举个例子?好啊,百万行的表划分为10个分区,每个分区就包含十万行数据,那么查询分区需要的时间仅仅是全表扫描的十分之一了,很明显的对比。同时对十万行的表建立索引的速度也会比百万行的快得多得多。如果你能把这些分区建立在不同的磁盘上,这时候的I/O读写速度就“不堪设想”(没用错词,真的太快了,理论上100倍的速度提升啊,这是多么快的响应速度啊,所以有点不堪设想了)了。

对数据管理的简化(Simplified data management) - 分区技术可以让DBA对数据的管理能力提升。通过优良的分区,DBA可以简化特定数据操作的执行方式。例如:DBA在对某些分区的内容进行删除的同时能保证余下的分区的数据完整性(这是跟对表的数据删除这种大动作做比较的)。

此外分区是由MySQL系统直接管理的,DBA不需要手工的去划分和维护。例如:这个例如没意思,不讲了,如果你是DBA,只要你划分了分区,以后你就不用管了就是了。

站在性能设计的观点上,俺们对以上的内容也是相当感兴趣滴。通过使用分区和对不同的SQL操作的匹配设计,数据库的性能一定能获得巨大提升。下面咱们一起用用这个MySQL 5.1的新功能看看。 

下面所有的测试都在Dell Optiplex box with a Pentium 4 3.00GHz processor, 1GB of RAM机器上(炫耀啊……),Fedora Core 4和MySQL 5.1.6 alpha上运行通过。

如何进行实际分区

看看分区的实际效果吧。我们建立几个同样的MyISAM引擎的表,包含日期敏感的数据,但只对其中一个分区。分区的表(表名为part_tab)我们采用Range范围分区模式,通过年份进行分区:

mysql> CREATE TABLE part_tab

    ->      ( c1 int default NULL,

    -> c2 varchar(30) default NULL,

    -> c3 date default NULL

    ->

    ->      ) engine=myisam

    ->      PARTITION BY RANGE (year(c3)) (PARTITION p0 VALUES LESS THAN (1995),

    ->      PARTITION p1 VALUES LESS THAN (1996) , PARTITION p2 VALUES LESS THAN (1997) ,

    ->      PARTITION p3 VALUES LESS THAN (1998) , PARTITION p4 VALUES LESS THAN (1999) ,

    ->      PARTITION p5 VALUES LESS THAN (2000) , PARTITION p6 VALUES LESS THAN (2001) ,

    ->      PARTITION p7 VALUES LESS THAN (2002) , PARTITION p8 VALUES LESS THAN (2003) ,

    ->      PARTITION p9 VALUES LESS THAN (2004) , PARTITION p10 VALUES LESS THAN (2010),

    ->      PARTITION p11 VALUES LESS THAN MAXVALUE );

Query OK, 0 rows affected (0.00 sec)

注意到了这里的最后一行吗?这里把不属于前面年度划分的年份范围都包含了,这样才能保证数据不会出错,大家以后要记住啊,不然数据库无缘无故出错你就爽了。那下面我们建立没有分区的表(表名为no_part_tab):

mysql> create table no_part_tab

    -> (c1 int(11) default NULL,

    -> c2 varchar(30) default NULL,

    -> c3 date default NULL) engine=myisam;

Query OK, 0 rows affected (0.02 sec)

下面咱写一个存储过程(感谢Peter Gulutzan给的代码,如果大家需要Peter Gulutzan的存储过程教程的中文翻译也可以跟我要,chenpengyi◎gmail.com),它能向咱刚才建立的已分区的表中平均的向每个分区插入共8百万条不同的数据。填满后,咱就给没分区的克隆表中插入相同的数据:

mysql> delimiter //

mysql> CREATE PROCEDURE load_part_tab()

    -> begin

    -> declare v int default 0;

    ->          while v < 8000000

    -> do

    -> insert into part_tab

    -> values (v,'testing partitions',adddate('1995-01-01',(rand(v)*36520) mod 3652));

    -> set v = v + 1;

    -> end while;

    -> end

    -> //

Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;

mysql> call load_part_tab();

Query OK, 1 row affected (8 min 17.75 sec)

mysql> insert into no_part_tab select * from part_tab;

Query OK, 8000000 rows affected (51.59 sec)

Records: 8000000 Duplicates: 0 Warnings: 0

表都准备好了。咱开始对这两表中的数据进行简单的范围查询吧。先分区了的,后没分区的,跟着有执行过程解析(MySQL Explain命令解析器),可以看到MySQL做了什么:

mysql> select count(*) from no_part_tab where

    -> c3 > date '1995-01-01' and c3 < date '1995-12-31';

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

| count(*) |

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

|   795181 |

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

1 row in set (38.30 sec)

mysql> select count(*) from part_tab where

    -> c3 > date '1995-01-01' and c3 < date '1995-12-31';

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

| count(*) |

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

|   795181 |

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

1 row in set (3.88 sec)

mysql> explain select count(*) from no_part_tab where

    -> c3 > date '1995-01-01' and c3 < date '1995-12-31'\G

*************************** 1. row ***************************

           id: 1

 select_type: SIMPLE

        table: no_part_tab

         type: ALL

possible_keys: NULL

          key: NULL

      key_len: NULL

          ref: NULL

         rows: 8000000

        Extra: Using where

1 row in set (0.00 sec)

mysql> explain partitions select count(*) from part_tab where

    -> c3 > date '1995-01-01' and c3 < date '1995-12-31'\G

*************************** 1. row ***************************

           id: 1

 select_type: SIMPLE

        table: part_tab

   partitions: p1

         type: ALL

possible_keys: NULL

          key: NULL

      key_len: NULL

          ref: NULL

         rows: 798458

        Extra: Using where

1 row in set (0.00 sec)

从上面结果可以容易看出,设计恰当表分区能比非分区的减少90%的响应时间。而命令解析Explain程序也告诉我们在对已分区的表的查询过程中仅对第一个分区进行了扫描,其他都跳过了。

哔厉吧拉,说阿说……反正就是这个分区功能对DBA很有用拉,特别对VLDB和需要快速反应的系统。

对Vertical Partitioning的一些看法

虽然MySQL 5.1自动实现了水平分区,但在设计数据库的时候不要轻视垂直分区。虽然要手工去实现垂直分区,但在特定场合下你会收益不少的。例如在前面建立的表中,VARCHAR字段是你平常很少引用的,那么对它进行垂直分区会不会提升速度呢?咱们看看测试结果:

mysql> desc part_tab;

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

| Field | Type        | Null | Key | Default | Extra |

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

| c1    | int(11)     | YES |     | NULL    |       |

| c2    | varchar(30) | YES |     | NULL    |       |

| c3    | date        | YES |     | NULL    |       |

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

3 rows in set (0.03 sec)

mysql> alter table part_tab drop column c2;

Query OK, 8000000 rows affected (42.20 sec)

Records: 8000000 Duplicates: 0 Warnings: 0

mysql> desc part_tab;

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

| Field | Type    | Null | Key | Default | Extra |

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

| c1    | int(11) | YES |     | NULL    |       |

| c3    | date    | YES |     | NULL    |       |

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

2 rows in set (0.00 sec)

mysql> select count(*) from part_tab where

    -> c3 > date '1995-01-01' and c3 < date '1995-12-31';

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

| count(*) |

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

|   795181 |

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

1 row in set (0.34 sec)

在设计上去掉了VARCHAR字段后,不止是你,俺也发现查询响应速度上获得了另一个90%的时间节省。所以大家在设计表的时候,一定要考虑,表中的字段是否真正关联,又是否在你的查询中有用?

补充说明 

这么简单的文章肯定不能说全MySQL 5.1 分区机制的所有好处和要点(虽然对自己写文章水平很有信心),下面就说几个感兴趣的:

支持所有存储引擎(MyISAM, Archive, InnoDB, 等等)

对分区的表支持索引,包括本地索引local indexes,对其进行的是一对一的视图镜像,假设一个表有十个分区,那么其本地索引也包含十个分区。

关于分区的元数据Metadata的表可以在INFORMATION_SCHEMA数据库中找到,表名为PARTITIONS。

All SHOW 命令支持返回分区表以及元数据的索引。

对其操作的命令和实现的维护功能有(比对全表的操作还多):

ADD PARTITION

DROP PARTITION

COALESCE PARTITION

REORGANIZE PARTITION

ANALYZE PARTITION

CHECK PARTITION

OPTIMIZE PARTITION

REBUILD PARTITION

REPAIR PARTITION

分享到:
评论

相关推荐

    MySQL分区分表方案实践手册

    MySQL的分区主要包括两种形式:水平分区和垂直分区。 - **水平分区(Horizontal Partitioning)**:这是一种基于表的行进行的分区方式,即根据某列的值将数据行划分到不同的分区中。例如,可以根据年份、日期等列的...

    MYSQL学习资料

    mysql水平分表和垂直分表和数据库分区 sysbench mysql 坚持不懈 sysbench安装和使用 SHOW INNODB STATUS 探秘 体验Innodb with Memcached –安装 数据切分及整合方案 数据库水平切分的实现原理解析 innodb max dirty...

    MySQL分区和分表技术总结.docx

    MySQL 分区和分表技术是数据库性能优化的重要手段,特别是在大型数据库系统中。以下是 MySQL 分区和分表技术的详细介绍: 什么是分表? 分表是将一个大表按照一定的规则分解成多张具有独立存储空间的实体表,每个...

    mysql分表创建

    1. **垂直分表**:根据字段的相关性将表分为多个部分,每个部分存储在不同的表中。例如,用户表可以将基本信息和交易记录分开,基本信息表包含ID、用户名、邮箱等,交易记录表包含ID、用户ID、交易时间等。这种方式...

    mysql分表,分区的区别与联系归类.pdf

    分表的常见方法包括垂直分表(按列拆分)和水平分表(按行拆分)。例如,使用Merge存储引擎,可以创建一个总表(如`alluser`),它并不存储实际数据,而是引用多个独立的分表(如`user1`和`user2`)。查询时,通过总...

    mysql分表,分区的区别与联系借鉴.pdf

    这通常通过不同的分表方法实现,如垂直分表(根据列的逻辑关系拆分)、水平分表(根据行数据分布拆分)或使用Merge存储引擎。分表后的数据处理发生在各个独立的小表中,通过一个总表或者中间件来协调查询,提高并发...

    mysql分表,分区的区别与联系[定义].pdf

    MySQL中的分表和分区是两种不同的数据库优化策略,它们旨在管理和优化大数据量的表,以提升查询性能和系统效率。 **分表**是指将一张大表拆分成多个小表,每个小表都是独立完整的表,拥有自己的.MYD数据文件、.MYI...

    MySQL 分库分表的实现原理及演示案例

    数据库分库分表的几种方式主要包括垂直分库、垂直分表、水平分库和水平分表。垂直分库是按照业务的不同进行数据库的分割,每个数据库只包含部分业务的数据;垂直分表是将一个表按照字段划分成多个表,通常按照数据的...

    MySQL数据库设计、优化.pptx

    MySQL数据库设计与优化是数据库管理中的重要环节,它关乎到系统的性能、稳定性和可扩展性。本讲座由叶金荣分享,主要涵盖了多个关键方面,包括规范、基础规范、命名规范、库表规范、字段规范、索引规范以及开发环境...

    一个MySQL分库分表php类

    当一个表数据记录过大时就会出现性能瓶颈,而一般对应的解决办法是要么做分区表,要么分表,分区表就不说了,分表又分为垂直分割和水平分割,具体区 别请自行搜索。一般而言,分库分表属于水平分割,按照一定的规则...

    MySQL数据库设计、优化

    通过对MySQL数据库的设计和优化规范的学习,我们可以了解到如何合理地规划数据库的各个方面,包括基础规范、命名规范、库表规范和字段规范等。这些规范的制定旨在提高数据库的整体性能,降低运维成本,并增强系统的...

    mysql分表和分区的区别浅析

    常见的分表策略包括垂直分表(按列划分)和水平分表(按行划分)。例如,使用Merge存储引擎进行分表,会创建一个总表(如alluser)作为接口,实际数据存储在各个分表(如user1和user2)中。总表并不存储数据,只是一...

    MySQL分表和分区的具体实现方法

    MySQL数据库在处理大数据量时,可能会遇到性能瓶颈...垂直分表适用于列多且锁竞争激烈的情况,水平分表和分区适用于数据量大、查询性能要求高的场景,而Merge存储引擎则为分片操作提供了透明性,简化了应用程序的处理。

    优化MySQL数据库性能的八大妙手.rar

    分表则通过水平切分或垂直切分,将数据分散到多个表中,减轻单表压力。 八、复制与负载均衡 数据库复制可以提高可用性和容错性,同时也可实现读写分离,减轻主库压力。设置读写分离后,读操作可以在从库上执行,...

    MySQL大厂面试题甄选,150道mysql数据库高频面试题讲解 MySQL数据库面试题宝典,mysql面试必考!msql工作必

    2. 水平与垂直分表:理解这两种分表策略,知道何时选择水平分表(根据业务属性)和垂直分表(根据列的关联性)。 六、复制与主从同步 1. 主从复制:了解主从架构,掌握配置MySQL主从复制的过程,理解binlog、relay ...

    MyCat实现MySQL分库分表.docx

    * 可以实现数据的水平分区和垂直分区 七、MyCat 的应用场景 * 大型电商平台的数据库分库分表 * 高并发的数据库应用场景 * 需要高性能和高可扩展性的数据库应用场景 八、MyCat 的配置项 * server.xml 文件配置 * ...

    一个MySQL分库分表php类.zip

    当一个表数据记录过大时就会出现性能瓶颈,而一般对应的解决办法是要么做分区表,要么分表,分区表就不说了,分表又分为垂直分割和水平分割,具体区 别请自行搜索。一般而言,分库分表属于水平分割,按照一定的规则...

    MySQL数据库面试题.pdf

    30. **垂直分表和水平分表的区别**:垂直分表是将表拆分成多个表,每个表包含原表的一部分列;水平分表则是将表按行分成多个表。它们有助于提高性能和可扩展性。 #### 四、复制与备份 31. **MySQL复制**:MySQL...

Global site tag (gtag.js) - Google Analytics