2016-07-03 40 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使用情況。