首页 理论教育PHPMVC开发实战-数据表分区的效能和原因

PHPMVC开发实战-数据表分区的效能和原因

【摘要】:上述代码表示创建tpk_user数据表时,将创建5个HASH分区。连续重复同样操作,t2数据表将很快达到存储极限,使用这种方式可以有效地测试数据表分区和数据表索引性能。数据表分区后,在应用层是不需要做任何更改的,这也是笔者建议读者使用数据表分区功能的最主要原因。

使用数据库读写分离能够有效地解决流量负载,提高连接并发,是大型网站常用的技术。但只有读写分离还不能解决前面提到过的1亿条数据存储的问题。通常情况下,管理员会将这1亿条数据进行水平分库,但这对于开发人员来说需要面临众多的问题,尤其是过多切换数据库将降低开发效率和运行效率,并且其后期程序扩展及维护是非常困难的。

商业数据库通常会使用数据表水平分区功能来处理超大型数据。MySQL 5.1以上版本(社区版)通过插件的方式能够完美支持表分区功能,便得MySQL的储存性能得到了质的提升。ThinkPHP本身也参照了MySQL表分区功能,提供了简单的数据库分表功能。事实上,所谓的数据库分表是在开发人员手动创建数据表的基础上,然后根据设定的规则,分步对各表进行操作,实现应用层面上的简单分表功能。由于处理逻辑在程序内实现,这对数据库的后期维护无疑是困难的,所以本节将介绍MySQL中的表分区功能,代替ThinkPHP中的数据分表功能。

1.数据表分区概述

在MyISAM引擎中,传统的数据库文件1个表对应3个文件。以tpk_user为例,用于存放表结构的tpk_user.frm;用于存放数据的tpk_user.MYD;以及用于存放索引文件的tpk_user.MYI。随着数据的快速增长,tpk_user.MYD和tpk_user.MYI文件大小也会激增,如果单个文件超过4GB,那么数据库的IO操作将会明显变慢,频繁的操作将会使数据库系统读写变得困难,这时就需要将数据表文件进行切割,限制单个件在可控的大小之内。数据表分区技术就是用于切割数据表文件的一项实用技术,从MySQL 5.1开始以插件的方式提供,要查看数据库系统是否支持数据表分区功能,可以使用show plugins命令查看,如以下代码所示。

如果出现PARTITION插件,那么说明当前数据库系统支持表分区功能,否则需要在configure时加入相应的选项(--with-plugins=all--with-PARTITION)。如果是Windows下的MySQL,默认已经开启表分区功能。

2.表分区分类

在确保数据库系统支持表分区后,就可以创建表分区了。MySQL共支持4种分区类型,分别为RANGE、LIST、HASH、KEY。在生产环境下,最常用的是RANGE分区和LIST分区。

(1)RANGE分区

RANGE分区是根据分区规则中设定的字段值来分区的,设定的字段值必须是能够有序变化并唯一的数值,例如时间、id等。RANGE的分区规则不需要开始序列,只需要结尾序列即可。如以下代码所示。

如上述代码所示,表示使用RANGE分区,并且以id作为分区依据。当id到达3时则创建p0分区,依次类推;当id超过12时将存放于p4分区中。

(2)LIST分区

LIST分区与RANGE分区类似,RANGE分区的规则是连续区间,而LIST规则是根据指定的字段值是否与规则中的值相等,如果相等则创建,否则放弃。指定的字段通常为枚举类型的数据。如以下代码所示。

如上述代码所示,创建tpk_user数据表时,当class_id为1~8时创建p0分区;class_id为9~16时创建p1分区。也就是说,LIST分区是必须显式指定固定的数值的,而不像RANGE规则那样指定一个数据区间。需要注意的是,创建LIST分区时,数据表中不允许存在主键索引字段。

(3)HASH分区

HASH分区没有特定的分区规则,它使用的是随机分配的分区策略,在创建数据表时,只需要指定PARTITIONS数值,HASH分区则按照设备的值将数据随机存放到数据表分区中,如以下代码所示。

上述代码表示创建tpk_user数据表时,将创建5个HASH分区。

(4)KEY分区(www.chuimin.cn)

KEY分区类似于HASH分区,但HASH分区使用用户自定义的表达式,而KEY分区使用的哈希函数是由MySQL服务器提供。如以下代码所示。

通过前面的介绍,相信读者已经掌握了这4种最常见的分区技术,每种分区技术都有各自的特点,在实际应用开发中可以灵活选择。至此,前面提到的1亿条数据的存储方案相信读者也已经找能够解决。最后还需要索引步骤,由于MySQL调优不在本书讲述范畴,需要读者自行参阅相关MySQL书籍。

‰ 提示:要在数据库中模拟1亿条数据并非困难的事,这里提供一种快速创建数据的方法。首先在数据库中创建2个一模一样的数据表,命名为t1和t2。在t1表中手动插入10条数据,然后在MySQL命令行中运行insert into t2 select*from t1;,执行完一次成后,按键盘上的“↑”键,然后回车。这时将会看到t2表以1倍的数据量重复添加。连续重复同样操作,t2数据表将很快达到存储极限,使用这种方式可以有效地测试数据表分区和数据表索引性能。

3.分区管理

在创建分区时或者创建分区后可以对分区的文件指定存放位置。

(1)改变文件位置

默认情况下,数据表分区文件和数据表文件存放一起,如果为了便于管理,在创建时可以通过DATA DIRECTORY选项手动指定数据表分区文件存放位置,如以下代码所示。

如上述代码所示,DATA DIRECTORY指定分区数据文件存放位置;INDEX DIRECTORY指定分区表索引数据存放位置。

(2)删除分区

数据表分区创建完毕后,通常不需要作修改,但是如果执行删除操作,可以使用drop删除指定的数据表分区,命令如下。

(3)增加分区

增加分区和增加字段类似,可以使用alter进行操作,例如为RANGE增加新分区,可以执行以下操作。

(4)重置分区

如果发现以前分配的分区不符号数据存放需求,同样也可以使用alter来重新分配过,以RANGE分区为例,只需要重置PARTITION即可,如以下代码所示。

数据表分区后,在应用层是不需要做任何更改的,这也是笔者建议读者使用数据表分区功能的最主要原因。虽然使用PHP程序也能在一定程度上实现类似的功能,甚至性能更加好,但无论是从开发效率还是程序的后期维护来衡量,都不建议在PHP中完成。