MySQL - 使用子查询优化查询

时间:2018-05-09 20:10:02

标签: mysql

我目前有点困在需要一些优化的查询 - 我正在寻找一种方法如何优化(如果可能)以下查询(我不知道此刻该做什么:/):< / p>

SELECT count(distinct(pj.id)) as qty 
FROM `project_jobs` `pj` 
JOIN `projects` `p` ON pj.project_id = p.id AND p.status NOT IN ("CANCELED","DELETED","ARCHIVED") 

WHERE 
(
    (
        (pj.job_type_service_id IN (SELECT id FROM job_type_services WHERE job_type_id IN (4,2,3)))
        AND 
        (pj.new_status_id IN ("wip","completed","delivered"))
    ) 
    AND (pj.status<>'DELETED' AND pj.status<>'CANCELED')
) 
AND 
(pj.due_date >= '2010-04-01 00:00:00' AND pj.due_date <= '2018-05-09 23:59:59')

and exists 
(SELECT * FROM project_job_parents pjp
    WHERE pjp.project_job_id IN 
        (SELECT id FROM project_jobs WHERE job_type_id IN (1,24,7,8,32,34,33))
    and
    pjp.parent_id = pj.id
)

EXPLAIN提供以下信息:

enter image description here

这里有什么可以做的来优化和加速查询吗?

1 个答案:

答案 0 :(得分:0)

  1. EXISTS子查询通常比IN子查询表现得更好,至少在大多数MySQL版本中都是如此(转换下面的查询)。
  2. 您没有提供表结构,因此很难判断哪些索引存在以及它们包含哪些列。所以,我只需指定你应该拥有哪些索引。
  3. 要添加的索引:

    ALTER TABLE `job_type_services` ADD INDEX `job_type_services_idx_id_id` (`job_type_id`,`id`);
    ALTER TABLE `project_job_parents` ADD INDEX `project_job_parents_idx_id` (`parent_id`);
    ALTER TABLE `project_job_parents` ADD INDEX `project_job_parents_idx_id` (`project_job_id`);
    ALTER TABLE `project_jobs` ADD INDEX `project_jobs_idx_id_id_status_id` (`new_status_id`,`project_id`,`status`,`id`);
    ALTER TABLE `project_jobs` ADD INDEX `project_jobs_idx_id` (`job_type_service_id`);
    ALTER TABLE `project_jobs` ADD INDEX `project_jobs_idx_id` (`id`);
    ALTER TABLE `project_jobs` ADD INDEX `project_jobs_idx_id_id` (`job_type_id`,`id`);
    ALTER TABLE `projects` ADD INDEX `projects_idx_status_id` (`status`,`id`);
    

    已转换的查询:

    SELECT
            count(DISTINCT (`pj`.id)) AS qty 
        FROM
            `project_jobs` `pj` 
        JOIN
            `projects` `p` 
                ON `pj`.project_id = `p`.id 
                AND `p`.status NOT IN (
                    'CANCELED',
                'DELETED',
                'ARCHIVED') 
            WHERE
                (
                    (
                        (
                            EXISTS (
                                SELECT
                                    1 
                                FROM
                                    job_type_services 
                                WHERE
                                    job_type_services.job_type_id IN (
                                        4, 2, 3
                                    ) 
                                    AND `pj`.job_type_service_id = job_type_services.id
                            )
                        ) 
                        AND (
                            `pj`.new_status_id IN (
                                'wip', 'completed', 'delivered'
                            )
                        )
                    ) 
                    AND (
                        `pj`.status <> 'DELETED' 
                        AND `pj`.status <> 'CANCELED'
                    )
                ) 
                AND (
                    `pj`.due_date >= '2010-04-01 00:00:00' 
                    AND `pj`.due_date <= '2018-05-09 23:59:59'
                ) 
                AND EXISTS (
                    SELECT
                        * 
                    FROM
                        project_job_parents pjp 
                    WHERE
                        EXISTS (
                            SELECT
                                1 
                            FROM
                                project_jobs 
                            WHERE
                                project_jobs.job_type_id IN (
                                    1, 24, 7, 8, 32, 34, 33
                                ) 
                                AND pjp.project_job_id = project_jobs.id
                        ) 
                        AND pjp.parent_id = `pj`.id
                    )