mysql作为站点后端的重要数据落地组成部分,可谓是运用相当之广泛。在web应用中,往往庞大的数据会最终落地到mysql中,当一张mysql单表记录了上10亿的记录时,性能往往不会很理想,于是我们往往会将一张单表拆分成多张相同的分表。今天我们主要来讲如何合理的进行分表。
1、对一个字段进行分表:
这种分表方式,是我在工作中直接应用到的一种方式:
举一个简单的例子:
比如电商网站,需要记录用户的所有购买记录,如果将所有记录放入到一张表userbuy表中,势必会非常巨大。所以我们可以通过对用户userid进行分表处理,将不同用户的购买记录放入不同的分表中。具体做法如下:
我们预估业务量,将最初的userby表,扩展为100张相同表结构的userbuy_index表
原表结构如下:
userbuy:
分表结构相同,如下:
userbuy_0
所有的分表采用完全相同的表结构。
当需要新增一条分表记录时,过程如下:
首先对userid进行hash计算,得到hash值,该hash值必然是0-99,目的是将对应的userid数据,写入到同一张分表中。
目前通常采用的hash算法如下:
php代码:
[php] view plain copy
static public function getStringHash($string, $tab_count)
{/*{{{*/
$unsign = sprintf('%u', crc32($string));
if ($unsign > 2147483647) // sprintf u for 64 & 32 bit
{
$unsign -= 4294967296;
}
return abs($unsign) % $tab_count;
}/*}}}*/
简要来说就是对userid做crc32的hash计算,crc32计算结果为一个10进制数,在不同bit位的操作系统下,得到的值可能会不同,所以对其进行一个统一的处理,然后对这个自然数进行取余计算,取余的除数就是你的分表数,比如这里为100。
这样我们就得到了一个在0-99以内的表后缀数index,然后拼接固定的表前缀userbuy_,得到完整的分表表名userbuy_index
之后的操作和不分表情况下的写库操作一致,将数据插入到对应的表中即可。
截止目前写入部分的设计讲完。
但往往我们有许多查询需求,最简单的莫过于查询某一用户的购买记录,这一需求,直接可以通过userid,hash找到对应的分表,然后对直接直接select即可拿到对应的记录。
但查询需求往往不那么简单,所以我们需要对分表维护一些索引表,比如,维护一张购买了商品的用户列表userindex,方法通常是,启动一个服务端的定时脚本,对一定时间范围内,或者一定id范围内的数据进行group by去重,拿到对应的去重userid,然后再将这些新增userid插入到userindex表中。这样就不断维护起一张userindex表。
简单实用的mysql分表就介绍到此,以上分表策略基本可以解决单表过大导致的各种问题。