如何从mysql数据库加载数据更快?

时间:2016-07-03 06:06:51

标签: php mysql

我有一个html搜索表单,如下图所示:

enter image description here

在此搜索表单中,我需要搜索7个表格中的数据。在这7个表中,存储了超过11K的数据。因此我使用以下sql JOIN查询来获取结果。

但是如果例如,它需要花费很长时间来获得结果(有时显示错误信息)我搜索姓氏= s 。我的意思是如果表列中有大量数据。怎么能解决这个问题?我使用LIMIT,但我认为它在此查询中没有帮助,因为首先我必须搜索所有7个表格!

Sql Query:

$getSearch .= " cd.cdid, cd.family_name, cd.given_name, cd.department, cd.title, company.cid, company.company_name, users.nickname, contact_label.label_data  FROM
            contact_details as cd
            LEFT JOIN users ON users.user_id = cd.user_id
            LEFT JOIN company ON company.cid = cd.cid
            LEFT JOIN contact_docs ON contact_docs.cdid = cd.cdid
            LEFT JOIN userkeywords ON userkeywords . cdid = cd . cdid
            LEFT JOIN keywords ON keywords . kid = userkeywords . kid
            LEFT JOIN contact_label ON contact_label.cdid = cd.cdid
            WHERE 1=1 ";


    if(!empty($ad_company)){
        $getSearch .= "AND company.company_name LIKE '$ad_company%' ";
    }
    if(!empty($ad_fname)){
        $getSearch .= "AND cd.family_name LIKE '$ad_fname%' ";
    }
    if(!empty($ad_department)){
        $getSearch .= "AND cd.department LIKE '$ad_department%' ";
    }

    if(!empty($ad_mp)){
        $getSearch .= "AND cd.mp >= '$ad_mp' "; 
    }
    if(!empty($ad_e2)){
        $getSearch .= "AND cd.e2 >= '$ad_e2' "; 
    }
    if(!empty($ad_pl)){
        $getSearch .= "AND cd.pl >= '$ad_pl' "; 
    }
    if(!empty($ad_ap)){
        $getSearch .= "AND cd.ap >= '$ad_ap' "; 
    }
    if(!empty($ad_j2)){
        $getSearch .= "AND cd.j2 >= '$ad_j2' "; 
    }

    if(!empty($ad_agreater)){
        $getSearch .= "AND cd.age >= '$ad_agreater' ";  
    }
    if(!empty($ad_aless)){
        $getSearch .= "AND cd.age <= '$ad_aless' "; 
    }
    if(!empty($ad_agreater) && !empty($ad_aless)){
        $getSearch .= "AND cd.age BETWEEN '$ad_agreater' AND '$ad_aless'";  
    }


    if(!empty($ad_sgreater)){
        $getSearch .= "AND cd.comp >= '$ad_sgreater' "; 
    }
    if(!empty($ad_sless)){
        $getSearch .= "AND cd.comp <= '$ad_sless' ";    
    }
    if(!empty($ad_sgreater) && !empty($ad_sless)){
        $getSearch .= "AND cd.comp BETWEEN '$ad_sgreater' AND '$ad_sless'"; 
    }


    if(!empty($ad_noteterm)){    
        $ad_noteterm = preg_replace("/\{ASUSIBBIR\}(.+?)\s:\s(.+?)\{ASUSIBBIR\}/m", "$2", $ad_noteterm);
        $getSearch .= "AND LOCATE('$ad_noteterm', REPLACE (notesUpdate, '{ASUSIBBIR}', ' '))";
    }

    if(!empty($ad_cnote)){    
        $getSearch .= "AND LOCATE('$ad_cnote', cd.characterNotes)"; 
    }
    if(!empty($ad_twork)){    
        $getSearch .= "AND contact_label.label_data LIKE '%$ad_twork%'";    
    }
    if(!empty($ad_tmobile)){    
        $getSearch .= "AND cd.mobile_phone like '%$ad_tmobile%'";   
    }

    if(!empty($ad_resume)){    
        $getSearch .= "AND LOCATE('$ad_resume', contact_docs.file_content)";    //is this the resume? yes
    }

    if(!empty($ad_datefrom) && empty($ad_dateto)){    
            $getSearch .= "AND cd.created_date BETWEEN '$ad_datefrom'AND '$date'";  
    }

    if(!empty($ad_dateto) && empty($ad_datefrom)){    
        $getSearch .= "AND cd.created_date BETWEEN date('0000-00-00') AND '$ad_dateto' "; 
    }

    if(!empty($ad_datefrom) && !empty($ad_dateto)){
        $getSearch .= "AND cd.created_date BETWEEN '$ad_datefrom' AND '$ad_dateto'";    
    }

    if(!empty($ad_type)){    
        $getSearch .= "AND cd.type = '$ad_type' ";  
    }

    if(!empty($ad_wemail)){
        $getSearch .= "AND cd.email LIKE '$ad_wemail%'";    
    }

    if(!empty($ad_pemail)){
        $getSearch .= "AND cd.email_private LIKE '$ad_pemail%'";    
    }

    if(!empty($ad_title)){
        $getSearch .= "AND cd.title LIKE '$ad_title%'"; 
    }

    if(!empty($ad_source)){
        $getSearch .= "AND cd.source LIKE '$ad_source%'";   
    }


    if(!empty($ad_consultant)){
        $getSearch .= "AND users.nickname LIKE '%$ad_consultant%'"; 
    }

    if(!empty($ad_keyword)){
        $ad_keyword_param = str_replace(",","','",$ad_keyword);
        $getSearch .= " AND keywords.keywordName IN ('$ad_keyword_param') ";
    }

    $getSearch .= " GROUP BY cd.user_id, cd.cid, cd.cdid ";

    if(!empty($ad_keyword)){
        $ad_keyword_param = str_replace(",",",",$ad_keyword);
        $getSearch .= " ) as a WHERE keywordName LIKE '$ad_keyword_param%' ";
    }

    $f = microtime(true);
    //$getSearch .= "ORDER BY cd.given_name ASC";
    $getSearch .= "ORDER BY cd.given_name DESC LIMIT 10";
    $getSearch =  mysqli_query($link, $getSearch);

3 个答案:

答案 0 :(得分:0)

你需要做的第一件事就是规范你的数据库,MySQL对连接提供了很好的支持,但正如你所经历的那样,当使用三个以上的连接时它有几个回退,因此重新设计你的数据库是我的第一个建议

其他替代方法是使用存储过程或视图,这应该更快。

答案 1 :(得分:0)

希望所有联接都是必要的,这是一个巨大的查询,这需要很长时间和正常。希望你有所有需要的索引。

首先检查索引未命中在存储过程中尝试,因为在动态查询运行中,每次调用查询语句时,服务器端的DB驱动程序都必须进行解析,分析,计划和优化。将过程存储在服务器上要高效得多,数据库引擎可以预先编译和分析过程一次,然后将其提交到缓存并直接运行。

即使以上都不起作用,也有两种选择。

<强> 1。增加PHP时间限制

编辑php.ini

;;;;;;;;;;;;;;;;;;;
; Resource Limits ;
;;;;;;;;;;;;;;;;;;;

; Maximum execution time of each script, in seconds
; http://php.net/max-execution-time
; Note: This directive is hardcoded to 0 for the CLI SAPI
max_execution_time = 500  

或方法调用

ini_set('max_execution_time', 500);

<强> 2。重新设计查询

通过所有这些连接,显而易见的是查询速度很慢。您需要对表格进行反规范化(如果您对冗余数据没问题),或者您必须考虑在第一页中是否需要所有这些信息。

Ex:cd.cdid,cd.family_name,cd.given_name,cd.department,cd.title,company.cid可以显示在列表页面中,您可以在用户悬停/点击结果时显示其他详细信息(懒加载羽毛信息)

但是,当您搜索所有列时,可能无法实现。

答案 2 :(得分:0)

您必须为每个查询创建索引。 如果您搜索“名字”,该脚本会进行这样的查询。

select cd.cdid, cd.family_name, cd.given_name, cd.department, cd.title, company.cid, company.company_name, users.nickname, contact_label.label_data  FROM
        contact_details as cd
        LEFT JOIN users ON users.user_id = cd.user_id
        LEFT JOIN company ON company.cid = cd.cid
        LEFT JOIN contact_docs ON contact_docs.cdid = cd.cdid
        LEFT JOIN userkeywords ON userkeywords . cdid = cd . cdid
        LEFT JOIN keywords ON keywords . kid = userkeywords . kid
        LEFT JOIN contact_label ON contact_label.cdid = cd.cdid
        WHERE 1=1 AND cd.family_name LIKE 'SEARCH_WORD%'

Mysql必须有索引。

users table : indexed column = user_id (Maybe PK?)
company table : indexed column = cid (Maybe PK?)
contact_docs table : indexed column = cdid (Maybe PK?)
userkeywords table : indexed column = cdid (Maybe PK?)
keywords table : indexed column = kid (Maybe PK?)
contact_label table : indexed column = cdid (Maybe PK?)
contact_details table : indexed column = family_name, cid(Maybe PK?), cdid

并且,您必须通过EXPLAIN验证SQL使用。