2017-7-20更新
扩展:
用着这种方法可以做千万级的数据分页优化的,第二天我对数据库某张三千万数据的表进行测试,先查到有用的id或者uid,排序好,时间消耗第一次是0.7秒,接下来的是0.2-0.3秒,然后去做连表查询用where条件in(id/uid)这样几十条数据是0.1秒内可以拿到结果的,然后程序循环匹配数据,处理数据,0.1秒内,这样的思路,我目前测试到的三千万的分页在偏移量50W内,可以做到1S之内搞定,这种应该是比较容易实现的了吧
#今天大佬说有某个控制器在admin的机器上面经常打不不开,在线上服务器没问题,接到反馈后,查源码...
#分析了一下,问题出在,循环查数据库上面,不用问了,这页面打开差不多10S,还有大量的没用数据load进来了
#经过一番折腾,检查哪些关联条件没有索引,然后写出了第一种渣渣的方法,就是join,然后push上去,渣渣5.6秒吧,性能这么差,作为处女座的我怎么能忍,然后想起了limit偏移量大的优化问题,网上搜索一番,记得我之前的博客有过这类问题的文章,我一直觉得两年前自己写的UI很渣,就关闭了,找到了这个http://blog.youkuaiyun.com/chenyusbyongde/article/details/52954809帖子
#...一段时间过去了....想起了我那牛逼的舍友,哈哈哈哈!!!
#舍友说百万级的数据排序分页瓶颈在于join,一开始我还是半信半疑的,想了下之前的5W*5W的循环,那速真的有点慢...事实证明这个思路还是听准确的
#1.先排序一个表,0.2S limit+order,取到合适条件的uid,然后根据uid in查找其他表的所需数据
#2.数组循环嵌套循环,组装需要的数据,第二个循环符合条件就unset掉一个,break跳出,下次就可以减少一次循环
#3.注意在count为空的时候,提示客户端,没有搜索到结果跳出去,不然下面的循环和sql in条件会为空报错的
#ps.其实我废话几句sphinx等牛叉的搜索开源项目都是找uid返回uid给mysql,然后mysql根据索引in这样秒查的
/**
yangxignyi openweixin666@126.com 2017-07-13 11:52
*/
public function index()
{
$mix_search = trim(I('mix_search'));
/*按照旧方法改的,性能还是太慢,30W条数据真的好慢,4-7秒
$count = M('ucenter_member u')
->join("join pay_personal_info p on u.id=p.uid")
->join("left join pay_stu s on u.id=s.uid")
->join("join pay_member m on u.id=m.uid")
->where($where)
->count();
$Page = new \Think\Page($count, 10);
$list = M('ucenter_member u')
->join("join pay_personal_info p on u.id=p.uid")
->join("left join pay_stu s on u.id=s.uid")
->join("join pay_member m on u.id=m.uid")
->where($where)
->order("u.id desc")
->field
('u.id,u.username,u.score,u.reg_time,u.last_login_time,u.last_login_ip,m.status,m.nickname,m.login,p.credit_name')
->limit($Page->firstRow.','.$Page->listRows)
->select();
*/
//处理搜索
if($mix_search){
if (is_numeric($mix_search)) {
$tempwhere = " username =" . $mix_search;
$search = M("ucenter_member")->where($tempwhere)->field("id")->find();
//如果根据条件搜索到就有搜索条件
$search['id'] = $search['id'] ? $search['id'] : '-9999';
$where = " uid = " . $search['id'];
}else{
$where = " credit_name like '".$mix_search."%' ";
}
$count = M('personal_info')->where($where)->count();
}else{
$count = M('personal_info')->count();
}
$count || $this->error("您的条件,没有搜索到数据!");
$Page = new \Think\Page($count, 10);
$listTemp = M('personal_info')
->where($where)
->field("uid,credit_name")
->order("id desc")
->limit($Page->firstRow.','.$Page->listRows)
->select();
$ids=$list=[];//循环取出对应的uid
foreach($listTemp as $v){
$ids[] = $v['uid'];
}
file_log("user-index",json_encode($ids));
$map['u.id'] = array('in',$ids);
$info = M("ucenter_member u")
->join("left join pay_stu s on u.id=s.uid")
->join("join pay_member m on u.id=m.uid")->where($map)
->field('u.id,u.username,u.score,u.reg_time,u.last_login_time,u.last_login_ip,m.status,m.nickname,m.login')
->select();
foreach($listTemp as $v){
foreach($info as $kk=>$vv){
if($v['uid']==$vv['id']){
$v['id'] = $vv['id'];
$v['username'] = $vv['username'];
$v['score'] = $vv['score'];
$v['reg_time'] = $vv['reg_time'];
$v['last_login_time'] = $vv['last_login_time'];
$v['last_login_ip'] = $vv['last_login_ip'];
$v['status'] = $vv['status'];
$v['nickname'] = $vv['nickname'];
$v['login'] = $vv['login'];
unset($vv[$kk]);break;
}
}
$list[] = $v;
}
$Page->setConfig('theme', '%HEADER% %FIRST% %UP_PAGE% %LINK_PAGE% %DOWN_PAGE% %END%');
$Page->parameter = $mix_search;
$show = $Page->show();
$this->assign('_list', $list);
$this->assign('_page', $show);
$this->meta_title = '用户信息';
$this->display();
}