为什么这个带有嵌套WHERE子查询的SELECT语句在MYSQL中运行缓慢?

时间:2014-12-24 04:11:00

标签: mysql select subquery where

我编写了一个处理权限的复杂查询,为了使其工作,它在IF语句中包含一个嵌套的子查询,以仅匹配用户有权限的项,并匹配条件。

我不确定为什么它运行缓慢,并希望有关如何调查查询速度的帮助。

概述了这一点:(完整查询下面)

//Main table has many records

SELECT some field FROM tbl join some table WHERE

IF (

Subquery ( Sub-subquery () )

)

完整查询:

            -- Get Account By User Assign to
            SELECT 
            --  SQL_CALC_FOUND_ROWS acc.account_id,
                acc.`is_delete`,
                acc.test,   CONCAT('<strong>',acc.account_name,'</strong>') AS account_name_alias,
                CONCAT(u.first_name,' ',u.last_name) created_by_alias, 
                a.account_type_name,
                i.industry_name, 
                CONCAT(u1.first_name,' ',u1.last_name) 
                modified_by_alias,
                isp.isp_name,
                sp.service_plan_name,
                c.country_name,
                ci.city_name,
                d.district_name,
                co.commune_name

            FROM crm_accounts AS acc
            INNER JOIN crm_accounts_assignments asm ON acc.`account_id` = asm.`account_id`
            LEFT JOIN crm_users u ON acc.created_by = u.user_id
            LEFT JOIN crm_users u1 ON  acc.modified_by = u1.user_id
            LEFT JOIN crm_account_types a ON  acc.account_type = a.account_type_id
            LEFT JOIN crm_industries i ON  acc.industry_id = i.industry_id
            LEFT JOIN crm_isp_lists isp ON  acc.isp_id = isp.isp_id
            LEFT JOIN crm_service_plans sp ON  acc.service_plan_id = sp.service_plan_id
            LEFT JOIN crm_countries c ON  acc.country_id = c.country_id
            LEFT JOIN crm_cities ci ON  acc.city_id = ci.city_id
            LEFT JOIN crm_districts d ON  acc.district_id = d.district_id
            LEFT JOIN crm_communes co ON  acc.commune_id = co.commune_id
            WHERE acc.is_delete = 0  

            //This my sub query
            AND 

                IF (
                      (
                          CASE asm.`assign_type` 
                        WHEN 
                          EXISTS
                             (
                              SELECT 1 FROM crm_user_param_users upu1
                              INNER JOIN crm_users us1 ON upu1.`user1_id` = us1.`user_id`
                              WHERE upu1.`user_id` = 7  AND  upu1.`user1_id` = asm.`assign_to_id`
                              AND us1.`role_id` !=2 #User the same Role could not access each other
                              OR EXISTS 
                               (
                                 -- The same Role will be allow if exist at custom share access
                                 SELECT 1 FROM `crm_user_param_modules_custom_accesses` mca1
                                 WHERE mca1.`module_id` = 1 AND mca1.`user_id` = 7 AND mca1.`role_id` = 2 LIMIT 1
                               ) GROUP BY upu1.`user1_id` LIMIT 1 
                             )

                           OR  EXISTS 
                             ( 
                                -- Only account created by current user
                                SELECT 1 FROM crm_user_param_users upu2 
                                INNER JOIN crm_users us2 ON upu2.`user1_id` = us2.`user_id`
                                WHERE upu2.`user_id` = 7 AND acc.`created_by` = upu2.`user1_id`
                                AND us2.`role_id` !=2  #User the same Role could not access each other
                                OR EXISTS 
                                (
                                  -- The same Role will be allow if exist at custom share access
                                  SELECT 1 FROM `crm_user_param_modules_custom_accesses` mca2
                                  WHERE mca2.`module_id` = 1 AND mca2.`user_id` = 7 AND mca2.`role_id` =2 LIMIT 1
                                ) GROUP BY upu2.`user1_id` LIMIT 1

                              )
                            OR  acc.`created_by` = 7

                        THEN 1
                        ELSE 0
                          END
                      )= 1, 1,0
                ) = 1

                OR 

                IF (
                      (
                          CASE asm.`assign_type` 
                        WHEN 
                         EXISTS 
                          ( 
                            SELECT 1 FROM `crm_user_param_groups` upg1
                            INNER JOIN crm_users us1 ON upg1.`user_id` = us1.`user_id`
                            WHERE upg1.`user_id` = 7 AND upg1.`group_id` = asm.`assign_to_id`
                             AND us1.`role_id` !=2 #User the same Role could not access each other

                             -- The same Role will be allow if exist at custom share access -- 
                             OR EXISTS 
                             (
                               SELECT 1 FROM `crm_user_param_modules_custom_accesses` mca1
                                WHERE mca1.`module_id` = 1 AND mca1.`user_id` = 7 AND mca1.`role_id` = 2 LIMIT 1
                             )  LIMIT 1
                          ) 

                          -- Only Account created by current user group --
                          OR EXISTS 
                          ( 
                            SELECT 1 FROM `crm_user_param_groups` upg2 
                             INNER JOIN crm_users us2 ON upg2.`user_id` = us2.`user_id`
                            WHERE upg2.`group_id` = asm.`assign_to_id` AND us2.`user_id` = acc.`created_by`
                             AND us2.`role_id` !=2 #User the same Role could not access each other
                             OR EXISTS 
                              (
                                -- The same Role will be allow if exist at custom share access --
                                SELECT 1 FROM `crm_user_param_modules_custom_accesses` mca2
                                WHERE mca2.`module_id` = 1 AND mca2.`user_id` = 7 AND mca2.`role_id` =2 LIMIT 1
                              )  LIMIT 1

                          )
                        OR acc.`created_by` = 7

                        THEN 2
                        ELSE 0
                          END
                      )= 2, 1,0
                ) = 1

1 个答案:

答案 0 :(得分:2)

您需要查看很多原因,如果没有更多信息,则无法进行诊断。以下是一系列问题,按照我建议的方式解决问题,以帮助您入门:

首先,您的查询SARG能够吗? (https://en.wikipedia.org/wiki/Sargable)似乎很清楚它不是;给出嵌套的子查询。如果你可以改变它,它会快得多。 (也许是第三个问题?)

其次,您能否以不同的方式构建它,以便您不需要嵌套的子查询?

第三,你的子查询每次都运行相同的东西吗?您可能希望为此使用临时表,因此如果您确实需要嵌套的子查询,则仅执行一次性能命中。

第四,您的表是否已正确编入索引以优化查询?

最后,您可以尝试使用DBA来实际调查查询性能,并查看是否还有其他事情要做。