简体   繁体   中英

Very slow mysql request + php

The ideia is: select all professions from a table. After this count how many professionals have the profession id in his category column. The category column store the professions id's separeted by commas (1, 2, 3, 420). The professions table has 604 rows. I have the following piece of code:

<?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 = '';
            }
?>

My basic question is WHY this is so slow in Google Chrome? Its taking like 15 seconds to load entire page with these results in a html table. In Edge or Firefox is taking about 5 seconds. I heard about Chrome using so much memory lately but I don't believe its soo slowly. In time this is the first time I use the FIND_IN_SET function on mysql. Is that may are slowing down the request? Anyone knows what I'm doing wrong or how can be optimized? This is actualy working but we know that 15 seconds of waiting makes the user give up or think that page is not working. I have to say too that if I do the same consultation on my HeidiSQL it takes 1 second.

I recommend to normalize this:

The category column store the professions id's separeted by commas (1, 2, 3, 420)

This is an n:n relationship. Your layout:

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

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

The string operations (split the list, normalize internal, query result in to temp, ...) is very cost intensive. Better:

professionals:
id | ...
12 | ..


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

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

This would skip the COUNT(FIND_IN_SET(professions.id, professional.category) > 0) as a string operation (even twice):

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

etc. You might restructure the above query like this, as long as you won't actually need any column from professions.

You can add a unique index on the cols (pid, cid) in table profrelations as one professional actually can have one profession only one times.

Remark

The different behaviour in two browser might result from the server caching the query: You're doing the query with Chrome, it's slow, but the result gets cached. Next with FF, server will respond with the cached result as its the same query again - fast. Try it three times or the other way round, should then be the same in all browsers.

At first,
this operation COUNT(FIND_IN_SET(professions.id, professional.category) > 0) will not return result that you expected. Count in above expression will return 1 even if find_in_set returns 0 .
Secondly, I wouldn't use join in this case at all. This tables have no direct relation by identifiers.
I would optimize the query as following:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM