简体   繁体   中英

How to improve the performance of multiple left joins in MySQL?

I have a trouble performance when I made multiples left joins in a query. There are 10 left joins in my query, if I show the information of 5 left joins works so fast but if I show information more of 5 left joins (6,7,8,etc.) takes 30 seconds to show the information. Example:

This is my original query that takes 32 seconds

SELECT `users`.id,
       `directions`.`name`      AS `subgrupo_1`,
       `positions`.`name`       AS `subgrupo_2`,
       `sites`.`name`           AS `subgrupo_3`,
       `subgrupo_fours`.`name`  AS `subgrupo_4`,
       `subgrupo_fives`.`name`  AS `subgrupo_5`,
       `subgrupo_sixes`.`name`  AS `subgrupo_6`,
       `subgrupo_sevens`.`name` AS `subgrupo_7`,
       `subgrupo_eights`.`name` AS `subgrupo_8`,
       `subgrupo_nines`.`name`  AS `subgrupo_9`
       ....
       ....

If I comment some information like this, takes 0.18 seconds

SELECT `users`.id,
       `directions`.`name`      AS `subgrupo_1`,
       `positions`.`name`       AS `subgrupo_2`,
       `sites`.`name`           AS `subgrupo_3`,
       `subgrupo_fours`.`name`  AS `subgrupo_4`,
       `subgrupo_fives`.`name`  AS `subgrupo_5`,
       -- `subgrupo_sixes`.`name`  AS `subgrupo_6`,
       -- `subgrupo_sevens`.`name` AS `subgrupo_7`,
       -- `subgrupo_eights`.`name` AS `subgrupo_8`,
       -- `subgrupo_nines`.`name`  AS `subgrupo_9`
       ....
       ....

If I uncomment one information like this, takes 32 - 34 seconds

SELECT `users`.id,
       `directions`.`name`      AS `subgrupo_1`,
       `positions`.`name`       AS `subgrupo_2`,
       `sites`.`name`           AS `subgrupo_3`,
       `subgrupo_fours`.`name`  AS `subgrupo_4`,
       `subgrupo_fives`.`name`  AS `subgrupo_5`,
       `subgrupo_sixes`.`name`  AS `subgrupo_6`,
       -- `subgrupo_sevens`.`name` AS `subgrupo_7`,
       -- `subgrupo_eights`.`name` AS `subgrupo_8`,
       -- `subgrupo_nines`.`name`  AS `subgrupo_9`
       ....
       ....

If I comment one information and uncomment other information like this, takes 0.18 seconds

SELECT `users`.id,
       `directions`.`name`      AS `subgrupo_1`,
       `positions`.`name`       AS `subgrupo_2`,
       `sites`.`name`           AS `subgrupo_3`,
       -- `subgrupo_fours`.`name`  AS `subgrupo_4`,
       `subgrupo_fives`.`name`  AS `subgrupo_5`,
       `subgrupo_sixes`.`name`  AS `subgrupo_6`,
       -- `subgrupo_sevens`.`name` AS `subgrupo_7`,
       -- `subgrupo_eights`.`name` AS `subgrupo_8`,
       -- `subgrupo_nines`.`name`  AS `subgrupo_9`
       ....
       ....

I saw that If I get 5 information of my left joins works well but if I get 6 o more information of my left joins takes to time, no matter which information I get always take too long time if I get more than 6 left joins. Its crazy!!

*** EDITED I put the original query

SELECT `users`.id,
       `directions`.`name`      AS `subgrupo_1`,
       `positions`.`name`       AS `subgrupo_2`,
       `sites`.`name`           AS `subgrupo_3`,
       `subgrupo_fours`.`name`  AS `subgrupo_4`,
       `subgrupo_fives`.`name`  AS `subgrupo_5`,
       `subgrupo_sixes`.`name`  AS `subgrupo_6`,
       `subgrupo_sevens`.`name` AS `subgrupo_7`,
       `subgrupo_eights`.`name` AS `subgrupo_8`,
       `subgrupo_nines`.`name`  AS `subgrupo_9`
FROM   `users`
       LEFT JOIN `directions`
              ON `users`.`direction_id` = `directions`.`id`
                 AND `directions`.`deleted_at` IS NULL
       LEFT JOIN `positions`
              ON `users`.`position_id` = `positions`.`id`
                 AND `positions`.`deleted_at` IS NULL
       LEFT JOIN `sites`
              ON `users`.`site_id` = `sites`.`id`
                 AND `sites`.`deleted_at` IS NULL
       LEFT JOIN `subgrupo_fours`
              ON `users`.`subgrupo_4` = `subgrupo_fours`.`id`
                 AND `subgrupo_fours`.`deleted_at` IS NULL
       LEFT JOIN `subgrupo_fives`
              ON `users`.`subgrupo_5` = `subgrupo_fives`.`id`
                 AND `subgrupo_fives`.`deleted_at` IS NULL
       LEFT JOIN `subgrupo_sixes`
              ON `users`.`subgrupo_6` = `subgrupo_sixes`.`id`
                 AND `subgrupo_sixes`.`deleted_at` IS NULL
       LEFT JOIN `subgrupo_sevens`
              ON `users`.`subgrupo_7` = `subgrupo_sevens`.`id`
                 AND `subgrupo_sevens`.`deleted_at` IS NULL
       LEFT JOIN `subgrupo_eights`
              ON `users`.`subgrupo_8` = `subgrupo_eights`.`id`
                 AND `subgrupo_eights`.`deleted_at` IS NULL
       LEFT JOIN `subgrupo_nines`
              ON `users`.`subgrupo_9` = `subgrupo_nines`.`id`
                 AND `subgrupo_nines`.`deleted_at` IS NULL
WHERE  `users`.`user_profile_id` = 4
       AND users.id IN (SELECT patient_vaccinations.user_id
                        FROM   `patient_vaccinations`
                        WHERE  `patient_vaccinations`.`deleted_at` IS NULL)
       AND `users`.`deleted_at` IS NULL
GROUP  BY `users`.`id`
LIMIT  100 offset 0

You only provided the select clause, which usually does not contribute significantly to the performance problems your query may have. The select clause may also be slow in some cases, if it has to fill a lot of memory, but you can find out whether the select clause is your culprit by removing all columns and leaving the joins as they were:

select 1
from <your ten joined tables>;

If this is slow, which is probably the case, then you need to focus on the from and join clauses.

We know that some of the last five tables are making it slow. So, you will need to find out which table is the culprit. Try it with six tables (without the last 4) and then with seven tables and so on. If it was quick for n tables and is slow for n + 1 tables, then the (n + 1)th table is the culprit. Try indexing the fields you are using for your join . Also, it may be the case that there are too many records in the table which represents the culprit.

So, as a general rule, you will need to find what the culprit is, ignoring any further complications for the time being and try and optimize the culprit. If you are successful and the query is still slow, then find the next culprit and so on.

If you conclude that this is impossible, then structural or strategic changes might be needed, depending on your schema and project.

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