2015-09-27 144 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