我有以下在本地执行良好的查询(0.4执行时间是可以接受的):
SELECT categories.*, parameters_values.key, l.* FROM categories
JOIN parameters_values ON parameters_values.parameter_id = 2 AND parameters_values.country_id = 223
JOIN categories_countries ON categories.category_id = categories_countries.category_id AND categories_countries.country_id = 223
JOIN listings AS l ON l.listing_id = (
SELECT listings.listing_id FROM listings
JOIN listings_categories ON listings.listing_id = listings_categories.listing_id
JOIN categories AS c ON listings_categories.category_id = c.category_id
WHERE
(c.category_id = categories.category_id OR c.subcategory = categories.category_id) AND
CASE parameters_values.`key`
WHEN 1 THEN listings.transaction_type = 1 OR listings.transaction_type = 3
WHEN 2 THEN listings.transaction_type = 2 OR listings.transaction_type = 3
WHEN 3 THEN true
END AND
listings.country_id = 223 AND
listings.property_type = 1 AND
listings.active = 1 AND
listings.published_flag = 1 AND
st_intersects(
POINT(listings.lng, listings.lat),
(SELECT IFNULL(`l`.`polygon`, GET_SQUARE(`l`.`lat`, `l`.`lng`, `l`.`radius`, `l`.`country_id`))
FROM `locations` AS `l` WHERE `location_id` = 1 LIMIT 1)
)
LIMIT 1
) ORDER BY categories.subcategory, categories.`order`
它只是检查一个类别中列表的存在,那里有一个位置搜索,没有什么过于复杂。本地执行计划如下:
+----+--------------------+----------------------+--------+----------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------+---------+-------------------------------------+------+------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+----------------------+--------+----------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------+---------+-------------------------------------+------+------------------------------------------------+
| 1 | PRIMARY | parameters_values | ref | parameter_id,country_id | parameter_id | 8 | const,const | 3 | Using temporary; Using filesort |
| 1 | PRIMARY | categories_countries | ref | PRIMARY,categories_countries_country_id_foreign | categories_countries_country_id_foreign | 4 | const | 122 | Using index |
| 1 | PRIMARY | categories | eq_ref | PRIMARY | PRIMARY | 4 | cp.categories_countries.category_id | 1 | NULL |
| 1 | PRIMARY | l | eq_ref | PRIMARY,listings_listing_id_transaction_type | PRIMARY | 4 | func | 1 | Using where |
| 2 | DEPENDENT SUBQUERY | c | ALL | PRIMARY,categories_subcategory_foreign | NULL | NULL | NULL | 127 | Range checked for each record (index map: 0x5) |
| 2 | DEPENDENT SUBQUERY | listings_categories | ref | PRIMARY,listings_categories_category_id_foreign | listings_categories_category_id_foreign | 4 | cp.c.category_id | 273 | Using index |
| 2 | DEPENDENT SUBQUERY | listings | eq_ref | PRIMARY,listings_country_id_foreign,listings_country_created_at,listings_country_units_created_at,listings_listing_id_transaction_type | PRIMARY | 4 | cp.listings_categories.listing_id | 1 | Using where |
| 3 | SUBQUERY | l | const | PRIMARY | PRIMARY | 4 | const | 1 | NULL |
+----+--------------------+----------------------+--------+----------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------+---------+-------------------------------------+------+------------------------------------------------+
但是,查询似乎在服务器上的执行方式不同,因为后四行是:
| 2 | DEPENDENT SUBQUERY | listings | ref | PRIMARY,listings_country_id_foreign,listings_country_created_at,listings_country_units_created_at,listings_listing_id_transaction_type | listings_country_id_foreign | 4 | const | 18238 | Using where |
| 2 | DEPENDENT SUBQUERY | listings_categories | ref | PRIMARY,listings_categories_category_id_foreign | PRIMARY | 4 | cp.listings.listing_id | 1 | Using index |
| 2 | DEPENDENT SUBQUERY | c | eq_ref | PRIMARY,categories_subcategory_foreign | PRIMARY | 4 | cp.listings_categories.category_id | 1 | Using where |
| 3 | SUBQUERY | l | const | PRIMARY | PRIMARY | 4 | const | 1 | NULL |
+----+--------------------+----------------------+--------+----------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------+---------+-------------------------------------+-------+---------------------------------+
有趣的是,使用前一个计划而不使用密钥的搜索执行得非常好,但后者需要大约23秒才能执行。我怎么能告诉MySQL遵循相同的执行计划?