[英]How to optimize performance inside MySQL Query filtered via NOT IN or NOT EXISTS
通过添加一个查询过滤器,我查询的一项性能低下。
这是完整的查询:
SELECT
`c`.`categories_id`,
`c`.`section_id`,
`c`.`categories_status`,
IF(`c`.`categories_status` = 1, 'ON', 'OFF') AS `categories_status_name`,
TRIM(`cd`.`categories_name`) AS `categories_name`,
IF(`cd`.`concert_date` <> '',
DATE_FORMAT(STR_TO_DATE(`cd`.`concert_date`,'%d/%m/%Y'),'%d.%m.%Y'),
NULL
) AS `concert_date`,
TRIM(`cd`.`concert_time`) AS `concert_time`
FROM
`categories` `c`
JOIN `categories_description` `cd` ON `c`.`categories_id` = `cd`.`categories_id`
WHERE
`c`.`plan_id` > 2
AND
`c`.`categories_status` = '1'
AND
`cd`.`categories_id` NOT IN(
SELECT
`p`.`parent_id`
FROM
`products` `p`
WHERE
`p`.`product_type` = 'X'
AND
`p`.`parent_id` = `cd`.`categories_id`
GROUP BY `p`.`product_type`
)
GROUP BY `c`.`categories_id`
ORDER BY DATE_FORMAT(STR_TO_DATE(`cd`.`concert_date`,'%d/%m/%Y'),'%Y-%m-%d') DESC, `cd`.`categories_name` DESC
在此查询中,我有一个新的过滤器,添加的内容如下所示:
`cd`.`categories_id` NOT IN(
SELECT
`p`.`parent_id`
FROM
`products` `p`
WHERE
`p`.`product_type` = 'X'
AND
`p`.`parent_id` = `cd`.`categories_id`
GROUP BY `p`.`product_type`
)
我还尝试使用NOT EXISTS
另一种解决方案,但这更糟糕了:
NOT EXISTS (
SELECT
DISTINCT 1
FROM
`products` `p`
WHERE
`p`.`product_type` = 'X'
AND
`p`.`parent_id` = `cd`.`categories_id`
GROUP BY `p`.`product_type`
)
我的主要问题是,在添加此过滤器以删除包含X
产品的类别后,性能开始真的很差。 如果没有此过滤器页面加载,则大约需要0.5-0.8秒,但使用此过滤器页面加载则可能需要8到10秒。
谁能帮助我优化此查询?
这可能有效。 大多数引擎的NOT IN / NOT EXISTS都不是很好,除非它们在内部将查询修改为以下形式。 至少值得一试。
SELECT
`c`.`categories_id`,
`c`.`section_id`,
`c`.`categories_status`,
IF(`c`.`categories_status` = 1, 'ON', 'OFF') AS `categories_status_name`,
TRIM(`cd`.`categories_name`) AS `categories_name`,
IF(`cd`.`concert_date` <> '',
DATE_FORMAT(STR_TO_DATE(`cd`.`concert_date`,'%d/%m/%Y'),'%d.%m.%Y'),
NULL
) AS `concert_date`,
TRIM(`cd`.`concert_time`) AS `concert_time`
FROM
`categories` `c` JOIN `categories_description` `cd`
ON `c`.`categories_id` = `cd`.`categories_id`
LEFT JOIN `products` `p`
ON `p`.`parent_id` = `cd`.`categories_id`
AND `p`.`product_type` = 'X'
WHERE
`c`.`plan_id` > 2
AND
`c`.`categories_status` = '1'
AND
`p`.`parent_id` IS NULL
GROUP BY `c`.`categories_id`
ORDER BY DATE_FORMAT(STR_TO_DATE(`cd`.`concert_date`,'%d/%m/%Y'),'%Y-%m-%d') DESC, `cd`.`categories_name` DESC
这是我得到的最快的解决方案。
SELECT
`c`.`categories_id`,
`c`.`section_id`,
`c`.`categories_status`,
IF(`c`.`categories_status` = 1, 'ON', 'OFF') AS `categories_status_name`,
TRIM(`cd`.`categories_name`) AS `categories_name`,
IF(`cd`.`concert_date` <> '',
DATE_FORMAT(STR_TO_DATE(`cd`.`concert_date`,'%d/%m/%Y'),'%d.%m.%Y'),
NULL
) AS `concert_date`,
TRIM(`cd`.`concert_time`) AS `concert_time`
FROM
`categories` `c`
INNER JOIN `categories_description` `cd` ON `c`.`categories_id` = `cd`.`categories_id`
LEFT JOIN `products` `p` ON `p`.`parent_id` = `cd`.`categories_id`
WHERE
`c`.`plan_id` > 2
AND
`c`.`categories_status` = '1'
AND `p`.`product_type` != 'X'
GROUP BY `c`.`categories_id`
ORDER BY DATE_FORMAT(STR_TO_DATE(`cd`.`concert_date`,'%d/%m/%Y'),'%Y-%m-%d') DESC, `cd`.`categories_name` DESC
感谢@NigelRen,他让我知道如何解决此问题。 @Ronald提供几乎相同的解决方案,但比我的解决方案要慢一些(0.400秒)。
谢谢大家的帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.