我编写了一个处理权限的复杂查询,为了使其工作,它在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
答案 0 :(得分:2)
您需要查看很多原因,如果没有更多信息,则无法进行诊断。以下是一系列问题,按照我建议的方式解决问题,以帮助您入门:
首先,您的查询SARG能够吗? (https://en.wikipedia.org/wiki/Sargable)似乎很清楚它不是;给出嵌套的子查询。如果你可以改变它,它会快得多。 (也许是第三个问题?)
其次,您能否以不同的方式构建它,以便您不需要嵌套的子查询?
第三,你的子查询每次都运行相同的东西吗?您可能希望为此使用临时表,因此如果您确实需要嵌套的子查询,则仅执行一次性能命中。
第四,您的表是否已正确编入索引以优化查询?
最后,您可以尝试使用DBA来实际调查查询性能,并查看是否还有其他事情要做。