2016-07-03 23 views
0

我有一个HTML搜索表单这就好比是波纹管图像:如何从MySQL数据库加载数据更快?

enter image description here

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

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

SQL查询:

$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); 
+0

你真的需要规范化你的数据库。 –

+0

是的,我想是的,但你有什么想法吗? –

+0

另外你为什么使用'where 1 = 1'? –

回答

0

你需要做的是规范数据库的第一件事,MySQL有良好的支持,加入,但因为你已经经历过在使用三个以上的连接有几个回退,因此重新设计你的数据库是我的第一个建议。

其他的选择是使用存储过程或视图,应该更快。

0

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

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

即使以上所有不起作用,有2个选项。

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.重新设计的查询

所有这些连接都很明显,查询速度很慢。您需要取消规范表(如果您对冗余数据没问题),或者您必须考虑在第一页中是否需要所有这些信息。例如:cd.cdid,cd.family_name,cd.given_name,cd.department,cd.title,company.cid可以显示在列表页面中,当用户悬停/点击结果时,您可以显示其他详细信息(延迟加载羽毛信息)

但是,当您使用所有列进行搜索时,它可能是不可能的。

+0

基本上所有的数据都来自只有一个表,这是company_details作为CD,但我正在寻找所有7个表。 –

+0

好吧,我明白了,似乎你需要去任何一个去规范化的表。或者尝试存储过程 – Malinga

+0

okey。我正在使用mysqli到其他页面。是否有任何问题如果我只为此搜索页使用存储过程?如果可能的话,你可以向我展示我的查询吗? –

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使用情况。