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

标签 mysql select subquery where-clause

我写了一个处理权限的复杂查询,为了让它工作,它在 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

最佳答案

您需要查看的原因有很多,如果没有更多信息,则无法诊断。下面是一个问题列表,按照我建议解决它们的顺序排列,以帮助您入门:

首先,您的查询是否支持 SARG? ( https://en.wikipedia.org/wiki/Sargable ) 很明显事实并非如此;给定嵌套子查询。如果你能改变它,它会快得多。 (也许请看第三个问题?)

其次,你能否以不同的方式构建它,这样你就不需要嵌套的子查询?

第三,你的子查询每次都运行同样的东西吗?您可能希望为此使用临时表,这样如果您真的需要嵌套子查询,性能损失只会发生一次。

第四,您的表是否正确地建立了索引以优化查询?

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

关于mysql - 为什么这个带有嵌套WHERE 子查询的SELECT 语句在MYSQL 中运行缓慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27631359/

相关文章:

mysql - 视觉基本: Best way to share data/variables over network?

mysql - SQL 从具有相同列的行中选择最后一行

php - MySQL 中的子选择

mysql - Hash 和 salt MySQL 字段类型

php - 单选按钮值未传递给 php 函数

mysql - INSERT INTO 使用来自其他表的数据导致错误 1064

javascript - 自动选择 html 选择标签的前一个和下一个选项

mysql 在单个查询中比较销售/购买

MYSQL 选择包含另一个查询中所有内容的元素

mysql - 与同一实体的多个一对多关系