千万级数据分页优化-1秒内处理完毕

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.csdn.net/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();
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值