2015-09-27 120 views
1

理念是:從表中選擇所有職業。在此之後,有多少專業人士在他的專欄中列出了專業ID。類別列存儲職業ID的逗號分隔(1,2,3,420)。職業表有604行。 我有下面的代碼:非常緩慢的MySQL請求+ php

<?php 
$select_professions = mysql_query("SELECT * FROM professions"); 
    if(mysql_num_rows($select_professions) == "0"){ 
     echo"No registers in DB"; 
    }else{while($row_professions = mysql_fetch_assoc($select_professions)){ 
     $id = $row_professions['id']; 

     $count_profiles = mysql_query("SELECT 
     COUNT(FIND_IN_SET(professions.id, professional.category) > 0) AS profile_numbers 
             FROM 
              professions 
             INNER JOIN 
              professional 
             WHERE 
              FIND_IN_SET(professions.id,professional.category) > 0 
             AND 
              professions.id = $id 
             GROUP BY 
              professions.id"); 
     $reg_profiles = mysql_fetch_assoc($count_profiles); 
     $numProfiles = $reg_profiles['profile_numbers']; 
      if($numProfiles > 4){ 
       $style = 'display:none'; 
      }else{ 
       $style = ''; 
      } 
?> 

我的基本問題是,爲什麼這是谷歌瀏覽器這麼慢? 它採取像15秒加載整個頁面與這些結果在一個HTML表格。在Edge或Firefox中大約需要5秒。我聽說Chrome最近使用了這麼多的內存,但我不相信它慢。這是我第一次在mysql上使用FIND_IN_SET函數。這是否會減慢請求速度?任何人都知道我在做什麼錯,或者如何優化?這是真實的工作,但我們知道等待15秒會讓用戶放棄或認爲該頁面無法工作。我不得不說,如果我在HeidiSQL上做同樣的諮詢,它需要1秒。

+0

PHP是服務器端的瀏覽器無關 – 2015-09-27 05:16:32

+0

創建和使用視圖和存儲過程..從PHP調用它們並獲得其結果。還有一件事,瀏覽器與此無關。 :) – aimme

+0

FIND_IN_SET(professions.id,professional.category) – e4c5

回答

2

我建議以標準化的:

類別列存儲的職業ID的由逗號separeted(1, 2,3,420)

這是一個n:n關係。你的佈局:

professionals: 
id | catgeory 
12 | 1,2,4,50 

professions 
id | desc 
1 | prof A 
2 | prof B 
... 

字符串操作(拆分列表,歸一化內部,查詢結果到temp,...)是非常昂貴的。更好:

professionals: 
id | ... 
12 | .. 


profrelations 
pid | cid 
12 | 1 
12 | 2 
12 | 4 
12 | 50 

professions 
id | desc 
1 | prof A 
2 | prof B 
... 

這將跳過COUNT(FIND_IN_SET(professions.id, professional.category) > 0)爲字符串操作(甚至兩次):

SELECT COUNT(cid) AS profile_numbers from professionals, profrelations where 
professionals.id = profrelations.pid AND profrelations.pid = $id; 

等你可能重組這樣上面的查詢,只要你實際上並不需要任何職業專欄。

您可以在表profrelations的列(pid, cid)上添加一個唯一索引,因爲一位專業人員實際上只能擁有一個職業一次。

備註

兩個瀏​​覽器不同的行爲可能導致服務器緩存查詢:你正在做與瀏覽器的查詢,它的速度慢,但結果被緩存。接下來使用FF,服務器將以緩存的結果作爲相同的查詢進行響應 - 速度很快。嘗試三次或反過來,應該在所有瀏覽器中都是一樣的。

+0

謝謝你的解釋和代碼示例。這是非常明確的,並且我很同意這是更好的選擇,因爲我們減少了這些常見的2個請求。 –

1

起初,
此操作COUNT(FIND_IN_SET(professions.id, professional.category) > 0)將不會返回您所期望的結果。即使find_in_set返回0,上述表達式中的Count將返回1。其次,我不會在這種情況下使用連接。這些表格沒有標識符的直接關係。
我會優化查詢如下:

SELECT COUNT(professions.id) AS profile_numbers FROM professions, professional 
WHERE FIND_IN_SET(professions.id,professional.category) > 0 AND professions.id = $id 
GROUP BY professions.id 
+0

嘿!謝謝你的好評。我用它來測試,它真的工作,並減少FIND_IN_SET一個,這種方式真的沒有返回1的問題,如果0.更好! –

+0

不客氣! ) – RomanPerekhrest