对于引入数据库中间件的方式,好处是对原有业务代码侵入较少,数据集中处理,易于管理。坏处是布署复杂,需要分出精力去管理,而且增加了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(v){
v%4+1][] = $v;
}
foreach(k => $v){
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
redis->zRange("user_friends",
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语句查询。
网友评论