在日期之间搜索时,MYSQL的PHP​​查询速度慢

时间:2017-10-18 15:54:55

标签: php mysql codeigniter search

当我尝试通过我的搜索引擎(php系统)查询数据库列表时,我正在使用Codeigniter并且当前面临极慢的搜索结果。我认为这个问题与我的查询编码有很大关系,因为显示数据库的其他页面加载速度很快,但是当我在日期之间搜索数据库时却没有。当我执行搜索时,页面就像加载超过10分钟。请检查我的编码是否有问题或任何专家请为我提供更好的建议以改进我的编码:

public function get_transaction_record($search,$per_pg,$offset){
        $fill  = array((int)1);
        $temp  = array();
        $data  = array();
        $sQuery = "SELECT t.*,p.product_name,d.deposit_id,w.withdrawal_id,m.username,m.lucky_id,m.contact_no,u.username as admin,
                    b.name as bankname,b.holder_name, d.promo as prm, m.fullname, d.turnover as tover
                    FROM tbl_transaction t
                    INNER JOIN tbl_product p ON t.product_id = p.product_id
                    INNER JOIN tbl_member m ON m.member_id = t.member_id
                    LEFT JOIN tbl_deposit d ON t.transaction_id = d.transaction_id
                    LEFT JOIN tbl_withdrawal w ON t.transaction_id = w.transaction_id
                    INNER JOIN tbl_banks b ON t.bank_id = b.bankID
                                              LEFT JOIN tbl_promotion pro ON pro.promotion_id = d.promotion_id
                    LEFT JOIN tbl_user u ON u.user_id = t.admin_id WHERE 1 = ?  AND t.status != 9";

        if( strlen($search['date_from']) > 0  && strlen($search['date_to']) > 0  ){
            $sQuery .= ' AND date(t.date_create) BETWEEN ? ';
            array_push($fill,$search['date_from']);

            $sQuery .= ' AND ? ';
            array_push($fill,$search['date_to']);
        }else{
            if( strlen($search['date_from']) > 0 ){
                $sQuery .= ' AND date(t.date_create) = ? ';
                array_push($fill,$search['date_from']);
            }
            if( strlen($search['date_to']) > 0 ){
                $sQuery .= ' AND date(t.date_create) = ? ';
                array_push($fill,$search['date_to']);
            }
        }

        if( strlen($search['status']) > 0 ){
            $sQuery .= ' AND t.status = ? ';
            array_push($fill,$search['status']);
        }
                    if( strlen($search['contact_no']) > 0 ){
            $sQuery .= ' AND m.contact_no LIKE "%"?"%" ';
            array_push($fill,$search['contact_no']);
        }

        if( strlen($search['fullname']) > 0 ){
            $sQuery .= ' AND m.fullname LIKE "%"?"%" ';
            array_push($fill,$search['fullname']);
        }
        if( strlen($search['username']) > 0 ){
            $sQuery .= ' AND m.username LIKE "%"?"%" ';
            array_push($fill,$search['username']);
        }

        if( strlen($search['lucky_id']) > 0 ){
            $sQuery .= ' AND m.lucky_id = ? ';
            array_push($fill,$search['lucky_id']);
        }

        if( strlen($search['email']) > 0 ){
            $sQuery .= ' AND m.email LIKE "%"?"%" ';
            array_push($fill,$search['email']);
        }

        if( strlen($search['user_id']) > 0 ){
            $sQuery .= ' AND t.admin_id = ? ';
            array_push($fill,$search['user_id']);
        }

        if( strlen($search['product_id']) > 0 ){
            $sQuery .= ' AND t.product_id = ? ';
            array_push($fill,$search['product_id']);
        }

        if( strlen($search['bankID']) > 0 ){
            $sQuery .= ' AND t.bank_id = ? ';
            array_push($fill,$search['bankID']);
        }

        if( strlen($search['type']) > 0 ){
            $sQuery .= ' AND t.type = ? ';
            array_push($fill,$search['type']);
        }

        if( strlen($search['bankid2']) > 0 ){
            $sQuery .= ' AND w.bankid2 = ? ';
            array_push($fill,$search['bankid2']);
        }

    //    $sQuery .= " ORDER BY t.date_create DESC LIMIT ?,? ";
            $sQuery .= " ORDER BY t.date_create DESC LIMIT ?,? ";
        // $sQuery .= " ORDER BY CASE t.status WHEN 0 THEN 0 WHEN 1 THEN 1 WHEN -1 THEN 9 END, t.date_create DESC LIMIT ?,? ";
        array_push($fill,(int)$offset,(int)$per_pg);

        $query  = $this->db->query($sQuery, $fill );
        //echo $this->db->last_query();
        if($query->num_rows() > 0){
            foreach ($query->result() as $rows):
                $temp['bankname']       = $rows->bankname;
                $temp['holder_name']    = $rows->holder_name;
                $temp['ref']            = $rows->ref;
                $temp['username']       = $rows->username;
                $temp['fullname']       = $rows->fullname;
                $temp['lucky_id']       = $rows->lucky_id;
                $temp['admin']          = $rows->admin;
                $temp['contact_no']     = $rows->contact_no;
                $temp['product_name']   = $rows->product_name;
                                    $temp['promo']   = $rows->promo;
                $temp['transaction_id'] = $rows->transaction_id;

                $temp['member_id']      = $rows->member_id;
                $temp['type']           = $rows->type;
                $temp['product_id']     = $rows->product_id;
                $temp['deposit_id']     = $rows->deposit_id;
                $temp['withdrawal_id']  = $rows->withdrawal_id;
                $temp['amount']         = $rows->amount;
                                    $temp['turnover']         = $rows->turnover;
                $temp['status']         = $rows->status;
                $temp['remark']         = $rows->remark;
                $temp['day']            = $rows->day;
                $temp['month']          = $rows->month;
                $temp['year']           = $rows->year;
                $temp['date_create']    = $rows->date_create;
                $temp['date_update']    = $rows->date_update;
                $temp['create_by']      = $rows->create_by;
                                    $temp['prm']            = $rows->prm;
                                    $temp['tover']            = $rows->tover;
                                    if($rows->promotion_id > 0){
                                            $temp['promo'] = $this->get_promotion_details($rows->promotion_id);
                                    }else{
                                            $temp['promo'] = NULL;
                                    }
                array_push($data, $temp);
            endforeach;
        }
        return $data;
    }

更新了上述代码

IMG FOR tbl_transaction SHOW CREATE TABLE

感谢。

1 个答案:

答案 0 :(得分:1)

首先,您没有为事务表定义索引。因此,任何搜索都被迫进行表扫描。使用索引来加速搜索非常重要。

您可能会喜欢我的演示文稿How to Design Indexes, Really。或视频:https://www.youtube.com/watch?v=ELR7-RdU9XU

这可能是您创建的最重要的索引:

ALTER TABLE tbl_transaction ADD INDEX (create_date);

但即使你有一个索引,当你尝试搜索如下的表达式时,它也不能使用索引。

date(t.date_create) BETWEEN ? AND ?

您必须重写它,以便索引列是独立的:

t.date_create BETWEEN ? AND ?

但是这意味着你希望第一个参数被“覆盖”到时间00:00:00,第二个参数被“天花板”到时间23:59:59,以确保date_create与任何时间组件匹配您希望它匹配的日期范围。

if( strlen($search['date_from']) > 0  && strlen($search['date_to']) > 0  ){
    $from = search['date_from'] . ' 00:00:00'; 
    $to   = search['date_to']   . ' 23:59:59'; 

    $sQuery .= ' AND t.date_create BETWEEN ? AND ?';
    array_push($fill,$from);
    array_push($fill,$to);
}

同样,即使搜索某个特定日期,您仍需要进行范围:

else if( strlen($search['date_from']) > 0 ){
    $from = search['date_from'] . ' 00:00:00'; 
    $to   = search['date_from'] . ' 23:59:59'; 

    $sQuery .= ' AND t.date_create BETWEEN ? AND ?';
    array_push($fill,$from);
    array_push($fill,$to);
}

如果你阅读我关于设计索引的演示文稿,你会发现像create_date那样的范围条件意味着索引中的任何后续列都无助于搜索。您可以使用多列索引,但是相等条件中涉及的所有列必须位于索引的左侧。

此外,根据用户的搜索条件,您可能有多种情况可能存在,也可能不存在。这也很难优化,因为索引搜索仅从左到右使用索引的列。如果您因为搜索不需要而跳过列,则后续列将无效。

搜索中的另一种条件是与LIKE '%'?''匹配的文本模式,而不是相等条件。这些LIKE次搜索无法使用传统索引,但可以使用特殊fulltext search index。我也有一个演示文稿:Full Text Search Throwdown。视频:https://www.youtube.com/watch?v=V8yA8C3CZOc