数据列表(联表查询)优化

一、情况描述

我们在做后台数据列表(例如:订单列表、会员列表、活动列表~~之类的)时候,需要的数据往往需要查询两张或以上的数据表,一般情况下会有两种做法

1)联表查询(在这里先不考虑通过联表方法无法查询到想要的字段数据的情况)

2)查单表,循环处理查询其他表的信息

 

二、两种查询方法比较

针对以上两种情况呢,一般我们都会以为联表查询会比循环查询要快,其实实际情况并不是这样的,其实查单表,再循环查询其他表反而更快

这是为什么呢???其实我也不知道哈哈,下面给出一些我自己的猜测(具体哪个更快,建议各位同学自己动手写一下代码做实验!)

猜测

1)如果要查询的表数据量比较大,和其他表的关联关系也比较复杂(查一个字段需要关联两张表之类的),这样拼出来的sql语句其实是比较复杂和啰唆的;

2)联表查询的时候,并不像查单表一样(假设查20条数据)直接就查询返回20条记录的,它内部的关联关系比较复杂,例如订单表的member_id关系显示members表的uname,可能并不像我们用member_id来从members表里查询uname一样快捷,它要处理sql里的关联逻辑判断(具体是怎样我也并不懂~~);

3)可能你会说“如果用循环来查询,那不就要执行好多个sql语句(一条记录查一次),mysql连接也消耗大量的资源了吗??”;

4)其实实际上也不完全是这样,mysql连接是要浪费的(下面会有优化方法),不过总查询时间并不会比联表慢。你想一下,当你面对一个很复杂,逻辑很繁琐的问题的时候,相比于硬啃,当复杂问题分解成若干个容易处理的小问题,反而更快

5)以上都是一脸正经地胡说八道,具体性能如何,自己做实验测试!!

 

三、优化循环查询

上面说到用查单表再循环查询其它表的方法要比联表查询要快,但要消耗比较多的数据库连接,下面我们要说一下如何减少查询次数

1)循环查询的时候,我们一般都是通过一个id去其他表查询我们需要的数据(例如orders表member_id查询members表uname),每循环一次查询一次;

2)其实你有没有发现,每次查询的语句都是一样的??(例如:select uname from members where member_id='xxx'),既然是都一样的,那么我们为什么还要每一次都重复等于等于(=)地来查询??mysql不是还是in这个东西吗??

3)通过上面分析,我们知道,如果是一样的sql语句,只是查询条件值不同的话,干嘛不用in呢??( 例如:select uname from members where member_id in ('1','2') )

4)以上面案例为例的话,其实我们先循环出所以的member_id,再用in一次性查询所有的uname会更快,也只需要查询一次!!!!

5)所以剩下的问题就只是怎么把查询出来的uname再重新分配到每一条记录中去了

6)下面是我的逻辑实现代码, 仅供参考!!!

/**
     * 更高效的扩展列处理方法
     * add by tujia @2016.11.07
     * expression(表达式)说明
     * 1)前面两个参数是关联表的on条件(例如:rel_id=order_id)
     * 2)第三个参数是你要提取的字段的名字(例如:t_payed)
     * 3)示例:rel_id=order_id=t_payed,member_id=member_id=login_account
     */
    protected function nice_row_data(&$data, $sql, $expression){
        $ttt = explode('=', $expression);

        foreach ($data as $key => $value) {
            $ids[] = $value[$ttt[1]];
        }
        $ids = implode("','", $ids);

        $sql = sprintf($sql, $ids);

        $list       = $this->db->select($sql);
        $temp       = array(); 
        foreach ($list as $key => $value) {
            $temp[$value[$ttt[0]]] = $value[$ttt[2]];
        }
        foreach ($data as $key => $value) {
            $data[$key][$ttt[2]] = isset($temp[$value[$ttt[1]]])? $temp[$value[$ttt[1]]] : 0;
        }
    }

使用示例:

$sql = "SELECT `rel_id`,`t_payed` FROM `sdb_ectools_order_bills` ob LEFT JOIN `sdb_ectools_payments` p ON p.`payment_id` = ob.`bill_id` WHERE ob.`rel_id` IN ('%s') AND p.`status`='succ'";

$this->nice_row_data($data, $sql, 'rel_id=order_id=t_payed');

 

补充说明:$data 是 已经查询出来的 单表数据

 

posted @ 2016-11-08 15:02  Tiac  阅读(3633)  评论(0编辑  收藏  举报