优化多个JOIN

时间:2018-01-18 09:59:29

标签: mysql join

我需要优化这个非常慢的查询。

SELECT SQL_CALC_FOUND_ROWS null as rows, `o`.`id`
FROM `objects` AS `o`
LEFT JOIN `geo_regions` AS `r` ON `r`.`id` = `o`.`region_id`
JOIN `object_features` AS `of1` ON `of1`.`object_id` = `o`.`id` AND `of1`.`feature_id` = 1
JOIN `object_features` AS `of2` ON `of2`.`object_id` = `o`.`id` AND `of2`.`feature_id` = 17
JOIN `object_features` AS `of3` ON `of3`.`object_id` = `o`.`id` AND `of3`.`feature_id` = 19
JOIN `object_features` AS `of4` ON `of4`.`object_id` = `o`.`id` AND `of4`.`feature_id` = 20
JOIN `object_features` AS `of5` ON `of5`.`object_id` = `o`.`id` AND `of5`.`feature_id` = 24
JOIN `object_features` AS `of6` ON `of6`.`object_id` = `o`.`id` AND `of6`.`feature_id` = 26
JOIN `object_features` AS `of7` ON `of7`.`object_id` = `o`.`id` AND `of7`.`feature_id` = 3
JOIN `object_features` AS `of8` ON `of8`.`object_id` = `o`.`id` AND `of8`.`feature_id` = 4
JOIN `object_features` AS `of9` ON `of9`.`object_id` = `o`.`id` AND `of9`.`feature_id` = 8
JOIN `object_features` AS `of10` ON `of10`.`object_id` = `o`.`id` AND `of10`.`feature_id` = 15
JOIN `object_features` AS `of11` ON `of11`.`object_id` = `o`.`id` AND `of11`.`feature_id` = 14
JOIN `object_features` AS `of12` ON `of12`.`object_id` = `o`.`id` AND `of12`.`feature_id` = 9
JOIN `object_features` AS `of13` ON `of13`.`object_id` = `o`.`id` AND `of13`.`feature_id` = 5
JOIN `object_features` AS `of14` ON `of14`.`object_id` = `o`.`id` AND `of14`.`feature_id` = 7
WHERE `object_type` = 1
AND `r`.`country` = '3'
AND (o.region_id = 20 OR o.region_id_2 = 20)
AND (o.city_id = 1175 )
AND `o`.`status` = 1
AND `o`.`type` IN('1', '0', '2')
AND `o`.`max_persons` >= '8'
AND `o`.`animals` = '1'
GROUP BY `o`.`id`
ORDER BY `o`.`all_ranking` DESC

我想找到具有一些所选功能的对象。功能存储在表“object_features”中。 我已经为所有必要的列设置了索引。

我的想法是只使用多个AND条件进行一次连接。像:

SELECT SQL_CALC_FOUND_ROWS null as rows, `o`.`id`
FROM `objects` AS `o`
LEFT JOIN `geo_regions` AS `r` ON `r`.`id` = `o`.`region_id`
 JOIN `object_features` AS `of1` ON `of1`.`object_id` = `o`.`id` AND `of1`.`feature_id` = 1 AND `of1`.`feature_id` = 24

WHERE `object_type` = 1

AND `r`.`country` = '3'
AND (o.region_id = 20 OR o.region_id_2 = 20)
AND (o.city_id = 1175 )
AND `o`.`status` = 1
AND `o`.`type` IN('1', '0', '2')
#AND `o`.`max_persons` >= '8'
#AND `o`.`animals` = '1'
GROUP BY `o`.`id`
ORDER BY `o`.`all_ranking` DESC

但这不起作用。

1 个答案:

答案 0 :(得分:1)

SET @featureidlist = '1, 17, 19, 24, 26, 3, 4, 8, 15, 14, 9, 5, 7'; 
SET @cnt = LENGTH(@featureidlist) - LENGTH(REPLACE(@featureidlist ,',','')) + 1;
SELECT @cnt;


SELECT SQL_CALC_FOUND_ROWS null as rows,
    o.id
FROM objects o
WHERE EXISTS  
(
    SELECT 1 FROM geo_regions r WHERE r.country = '3' AND r.id =  o.RegionId
)
AND EXISTS  
(
    SELECT 1 FROM object_features obf WHERE obf.feature_id IN (1, 17, 19, 24, 26, 3, 4, 8, 15, 14, 9, 5, 7) AND obf.object_id = o.id GROUP BY obj.object_id HAVING COUNT(DISTINCT obf.feature_id) = @cnt
)
AND o.object_type = 1
AND (o.region_id = 20 OR o.region_id_2 = 20)
AND o.city_id = 1175
AND o.status = 1
AND o.type IN('1', '0', '2')
AND o.max_persons >= '8'
AND o.animals = '1'
ORDER BY o.all_ranking DESC;