SELECT COUNT with low performance in mysql

Asked

Viewed 158 times

-1

I use a query within PHP to display the list of related categories and subcategories, get back more than 10,000 results (right) in 3 seconds on average, but after I implemented a subquery to check the amount of related subcategories, the query oscillated between 15-17 seconds.

No SUBQUERY (3s on average):

$sql_query = "SELECT t.* FROM `table` t 
WHERE 
    t.`tbl_id` = '".mysqli_fetch_array($dbconn,$id)."' 
ORDER BY 
    (CASE WHEN t.`tbl_nome` = 'Outros' THEN 1 ELSE 0 END) ASC, 
t.`tbl_nome` ASC;

With SUBQUERY (15> on average):

$sql_query = "SELECT t.*,
(SELECT COUNT(n.`tbl_id`) FROM `categoria` n WHERE n.`tbl_pai` = t.`tbl_id` LIMIT 1) 
AS `numSubs` 
FROM 
    `table` t 
WHERE 
    t.`tbl_id` = '".mysqli_fetch_array($dbconn,$id)."' 
ORDER BY 
    (CASE WHEN t.`tbl_nome` = 'Outros' THEN 1 ELSE 0 END) ASC, 
t.`tbl_nome` ASC;

inserir a descrição da imagem aqui

I added COUNT to check for other records in the field tbl_pai has different NULL ID and is the ID of the category to be consulted.

DOUBT:

There is another way to check if other fields have the current category ID in the field tbl_pai 1 only, which has the parent field with the current category ID. ? So optimize the query and stop slowing down?

  • 1

    Right, and what’s the question? :)

  • Can post table structure?

  • I got it, attached to the question =)

  • The worst is that the query is within a looping, and could not be done differently for the requested purpose.

  • What is the problem with the negativity of the question? At least they do not justify why.

  • Possibly negative before you edit.

  • It’s much easier if you post what you have inside the tables (at least as an example) and what you want to get. It gets very complicated to give an answer without having to test or having to invent data to test

  • @Sorack is that they are sensitive data, but they have some 10k+ and the structure is this only, the related data are in other tables but they are not used in this part of the code.

  • 2

    @Eliseub. If you do not question or put example data, that do not need to be the real ones but only that demonstrate your problem I will not make a point of trying to answer too. The least you could do is make it easier for those who try to help you.

  • @Sorack the problem is in the query, which dropped the performance when running it, does not need data, it is not data, it is more an optimization of it (query) or other relationship mode, I left well explained what is happening. Thank you!

  • 1

    @Eliseub. and how can anyone suggest an improvement of query ensuring that the data will not be altered?

  • 1

    you need to use EXPLAIN and post the result, so just know where is the performance problem

  • @Sorack the data will not be changed, are permanent data, I made the suggested improvement and then I made a DB cache system in static HTML, what changes is the product table, but it is good the performance there, this I do not need to worry, and the suggestion of INDEX.

Show 8 more comments

2 answers

3


Your query has inconsistencies (such as LIMIT in the COUNT), but without data for a more elaborate answer I can only suggest the following:

Create an index for your table:

ALTER TABLE categoria ADD INDEX categoria_index (tbl_pai);

More information on the answer to the question Indexes in Mysql queries and What is the INDEX index in Mysql for?.

  • I read several BD performance questions and realized that people today don’t do the simple thing that is to create indexes, make a performance diagnosis or create an execution plan. + 1

  • 1

    @Augustovasques as it is, I wanted the question to have data so that I could consult the execution plan, but as this was not informed I think that only the index should improve on something

  • 1

    It’s gotten a lot better, @Sorack sorry I don’t seem to care about my question, I took a risk knowing that at the very least I have to structure a good question to get help, but beyond the data I went through it would be risky, and inserting questions on my phone is horrible, thanks for your patience.

  • 1

    @Sorack Card, you are faster than before you enter COUNT =D

1

You can use other strategies, such as building a View by summarizing the number of sub-variables per tbl_parent:

Select tbl_pai, count(*) as qtde from categoria Group by tbl_pai

So, whenever you want, you can make a Join with this view.

In the model you are using, with 10 thousand categories, it will do a lot of processing item by item, I think you can try a code similar to the code below that calculates the amount of items per parent category at once and then Join with this result. (check the code, I’m no environment to test, but it would be something like below)

SELECT 
    t.campo1, t.campo2, t.campo3..., sum(n.qtde) as numSubs  --- como será um agrupamento. adicionar todos 
                                                             --- os campos necessário e depois adicionar no group by
From
    table t

    -- assumindo que todos os itens tem um filho pelo menos
    inner join (
        select  categoria.tbl_pai, 
                count(*) as qtde
        from    
                categoria 
        group by 
                tbl_pai) as n 

                on n.tbl_pai = t.tbl_id

WHERE 
    t.tbl_id = '<<condicao>>' 

GROUP BY 
    t.campo1, t.campo2, t.campo3, t.campo4.... -- adicionar todos os campos necessários

ORDER BY 
        (CASE WHEN t.tbl_nome = 'Outros' THEN 1 ELSE 0 END) ASC, 
        t.tbl_nome ASC;

Remember to list all the 'table' fields that you want to show both at the beginning of select, and at group by.

  • Tomorrow morning I will take the test, thank you for now, as soon as held post as it was whether it worked out with the performance, thank you from now!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.