免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2157 | 回复: 0

通过分区(Partition)提升MySQL性能 [复制链接]

论坛徽章:
0
发表于 2009-12-05 16:21 |显示全部楼层
什么是数据库分区?
数据库分区是一种物理数据库设计技术,DBA和数据库建模人员对其相当熟悉。虽然分区技术可以实现很多效果,但其主要目的是为了在特定的SQL操作中减少数据读写的总量以缩减响应时间。
分区主要有两种形式://这里一定要注意行和列的概念(row是行,column是列)
1. 水平分区(Horizontal Partitioning)这种形式分区是对表的行进行分区,通过这样的方式不同分组里面的物理列分割的数据集得以组合,从而进行个体分割(单分区)或集体分割(1个或多个分区)。所有在表中定义的列在每个数据集中都能找到,所以表的特性依然得以保持。
举个简单例子:一个包含十年发票记录的表可以被分区为十个不同的分区,每个分区包含的是其中一年的记录。(朋奕注:这里具体使用的分区方式我们后面再说,可以先说一点,一定要通过某个属性列来分割,譬如这里使用的列就是年份)
2. 垂直分区(Vertical Partitioning) 这种分区方式一般来说是通过对表的垂直划分来减少目标表的宽度,使某些特定的列 被划分到特定的分区,每个分区都包含了其中的列所对应的行。
举个简单例子:一个包含了大text和BLOB列的表,这些text和BLOB列又不经常被访问,这时候就要把这些不经常使用的text和BLOB了划分到另一个分区,在保证它们数据相关性的同时还能提高访问速度。
在数据库供应商开始在他们的数据库引擎中建立分区(主要是水平分区)时,DBA和建模者必须设计好表的物理分区结构,不要保存冗余的数据(不同表中同时都包含父表中的数据)或相互联结成一个逻辑父对象(通常是视图)。这种做法会使水平分区的大部分功能失效,有时候也会对垂直分区产生影响。
在MySQL 5.1中进行分区
MySQL5.1中最激动人心的新特性应该就是对水平分区的支持了。这对MySQL的使用者来说确实是个好消息,而且她已经支持分区大部分模式:
Range(范围) – 这种模式允许DBA将数据划分不同范围。例如DBA可以将一个表通过年份划分成三个分区,80年代(1980’s)的数据,90年代(1990’s)的数据以及任何在2000年(包括2000年)后的数据。
Hash(哈希) – 这中模式允许DBA通过对表的一个或多个列的Hash Key进行计算,最后通过这个Hash码不同数值对应的数据区域进行分区,。例如DBA可以建立一个对表主键进行分区的表。
Key(键值) – 上面Hash模式的一种延伸,这里的Hash Key是MySQL系统产生的。
List(预定义列表) – 这种模式允许系统通过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范围分区模式,通过年份进行分区:
   1. mysql> CREATE TABLE part_tab
   2. -> ( c1 int default NULL,
   3. -> c2 varchar(30) default NULL,
   4. -> c3 date default NULL
   5. ->
   6. -> ) engine=myisam
   7. -> PARTITION BY RANGE (year(c3)) (PARTITION p0 VALUES LESS THAN (1995),
   8. -> PARTITION p1 VALUES LESS THAN (1996) , PARTITION p2 VALUES LESS THAN (1997) ,
   9. -> PARTITION p3 VALUES LESS THAN (1998) , PARTITION p4 VALUES LESS THAN (1999) ,
  10. -> PARTITION p5 VALUES LESS THAN (2000) , PARTITION p6 VALUES LESS THAN (2001) ,
  11. -> PARTITION p7 VALUES LESS THAN (2002) , PARTITION p8 VALUES LESS THAN (2003) ,
  12. -> PARTITION p9 VALUES LESS THAN (2004) , PARTITION p10 VALUES LESS THAN (2010),
  13. -> PARTITION p11 VALUES LESS THAN MAXVALUE );
  14. Query OK, 0 rows affected (0.00 sec)
注意到了这里的最后一行吗?这里把不属于前面年度划分的年份范围都包含了,这样才能保证数据不会出错,大家以后要记住啊,不然数据库无缘无故出错你就爽了。那下面我们建立没有分区的表(表名为no_part_tab):
   1. mysql> create table no_part_tab
   2. -> (c1 int(11) default NULL,
   3. -> c2 varchar(30) default NULL,
   4. -> c3 date default NULL) engine=myisam;
   5. Query OK, 0 rows affected (0.02 sec)
下面咱写一个存储过程(感谢Peter Gulutzan给的代码,如果大家需要Peter Gulutzan的存储过程教程的中文翻译也可以跟我要,chenpengyi◎gmail.com),它能向咱刚才建立的已分区的表中平均的向每个分区插入共8百万条不同的数据。填满后,咱就给没分区的克隆表中插入相同的数据:
   1. mysql> delimiter //
   2. mysql> CREATE PROCEDURE load_part_tab()
   3. -> begin
   4. -> declare v int default 0;
   5. -> while v  do
   7. -> insert into part_tab
   8. -> values (v,’testing partitions’,adddate(’1995-01-01′,(rand(v)*36520) mod 3652));
   9. -> set v = v + 1;
  10. -> end while;
  11. -> end
  12. -> //
  13. Query OK, 0 rows affected (0.00 sec)
  14. mysql> delimiter ;
  15. mysql> call load_part_tab();
  16. Query OK, 1 row affected (8 min 17.75 sec)
  17. mysql> insert into no_part_tab select * from part_tab;
  18. Query OK, 8000000 rows affected (51.59 sec)
  19. Records: 8000000 Duplicates: 0 Warnings: 0
表都准备好了。咱开始对这两表中的数据进行简单的范围查询吧。先分区了的,后没分区的,跟着有执行过程解析(MySQL Explain命令解析器),可以看到MySQL做了什么:
   1. mysql> select count(*) from no_part_tab where
   2. -> c3 > date ‘1995-01-01′ and c3  select count(*) from part_tab where
  10. -> c3 > date ‘1995-01-01′ and c3  explain select count(*) from no_part_tab where
  18. -> c3 > date ‘1995-01-01′ and c3  explain partitions select count(*) from part_tab where
  32. -> c3 > date ‘1995-01-01′ and c3  desc part_tab;
   2. +——-+————-+——+—–+———+——-+
   3. | Field | Type | Null | Key | Default | Extra |
   4. +——-+————-+——+—–+———+——-+
   5. | c1 | int(11) | YES | | NULL | |
   6. | c2 | varchar(30) | YES | | NULL | |
   7. | c3 | date | YES | | NULL | |
   8. +——-+————-+——+—–+———+——-+
   9. 3 rows in set (0.03 sec)
  10. mysql> alter table part_tab drop column c2;
  11. Query OK, 8000000 rows affected (42.20 sec)
  12. Records: 8000000 Duplicates: 0 Warnings: 0
  13. mysql> desc part_tab;
  14. +——-+———+——+—–+———+——-+
  15. | Field | Type | Null | Key | Default | Extra |
  16. +——-+———+——+—–+———+——-+
  17. | c1 | int(11) | YES | | NULL | |
  18. | c3 | date | YES | | NULL | |
  19. +——-+———+——+—–+———+——-+
  20. 2 rows in set (0.00 sec)
  21. mysql> select count(*) from part_tab where
  22. -> c3 > date ‘1995-01-01′ and c3

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/37416/showart_2112014.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP