php业务层上如何处理分表后的数据

2020-08-07  本文已影响0人  回眸淡然笑

对于引入数据库中间件的方式,好处是对原有业务代码侵入较少,数据集中处理,易于管理。坏处是布署复杂,需要分出精力去管理,而且增加了proxy层,效率势必会减弱,所以说鱼和熊掌不可兼得,但是使用数据中间件是公司往高级业务发展的终极方向(如果说未来公司真的大了)。

对于mysql,在高并发访问时,容易引起表锁,所以分表可以在定程度上解决这个问题,分表方式不在具体细说,数据分表了,该如何操作。

举个例子:

下面有两个表,两个表各有一亿的数据。

用户表:members

uid:用户uid username:用户名 friends:好友数 regdate:注册日期

用户扩展信息表:members_profile
uid:用户uid province:省 address:地址

根据uid%4分表
members表被分成4个

members_1,members_2,members_3,members_4

members_profile同理

分表后带来什么改变:

members和membes_profile表基本没用了。可以保留7天然后删除。

members_n表的uid肯定不能自增,所以增加membersuid表,建立一个字段uid,设为主键并且自增。增加用户前,先往membersuid表插入一表数据,然后根据insert_id()获取uid。

1、分表前:select uid,username from members where uid in(1,2,3,4,5,6,7,8,9)一行获取数据

分表后:

对查询uid取模处理

//要查询的uid

$beforeUids = array(1,2,3,4,5,6,7,8,9);

$unionConditions = array();

$selectSql = array();

foreach(beforeUids asv){

unionConditions[v%4+1][] = $v;

}

foreach(unionConditions ask => $v){

selectSql[] = 'select uid,username from members_'.k.' where uid in('.implode(',',$v).')';

}

mysql_query(implode(' union ',$selectSql));

2、分表前:select uid,username from members where 1 order by friends desc limit ;

这里要按好友数降序排列,我们该怎么办,有一种方式是,分表前,我们需要建立一张索引表,先从索引表根据排序后查询出数据,然后在去查询分表的内容,但是,索引表容易过大,所以还是会成为瓶径,个人认为还有一种方案,启用redis的zset数据结构来专门存储friends的排序,因为zset自带排序光环。但是增加了业务更新和插入数据的业务逻辑,并且数据也产生冗余,但还是建议尽量增加where条件定位查询表。zset请自行百度查询

分表后:

1、从redis里获取根据friends排序好的uid

uids =redis->zRange("user_friends",limitStart,recordNums);

2、对uid取模,使用union联接查询mysql

3、因为取模后查询出来的数据是无序的,对查询出来的数据,在业务层上需要排序

4、输出数据

3、分表前:select uid,username from members where uid in(10,20,30,40) and friends > 20;

分表后:跟1的方式一样,分析where后面的查询,分解成select uid,username from members_1 where uid in(10,20,) and friends > 20 union....

4、分表前:select uid,username from members where username = “xxxx”

这种方式,个人建议,针对where后面的查询条件并且是字符串型的,使用开源的sphinx建立索引。

分表后:从sphinx根据username查询出uid,然后去mysql取数据

5、分表后的join查询,尽量修改成多条sql语句查询。

上一篇 下一篇

猜你喜欢

热点阅读